All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] Broadwel RC6 & RPS
@ 2014-01-29  4:25 Ben Widawsky
  2014-01-29  4:25 ` [PATCH 1/9] drm/i915: Clarify RC6 enabling Ben Widawsky
                   ` (9 more replies)
  0 siblings, 10 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky

This patch series implements RC6 and RPS for Broadwell. Most of the work
had already been done with the initial merge of Broadwell support,
however, there were a couple of missed things, and enough stuff had
moved around. The big change is the addition of the interrupt handlers.

I am mostly interested in getting RC6 working. RC6 enabling is critical
to getting other teams up and running. I decided to table RPS as well
because the code isn't quite as isolated as I would like, and the work
didn't seem that difficult.

IMPORTANT NOTE: With the current patch series, I do see rc6 residency
(not tested rps very much) however, the very first batch always GPU
hangs. At this point I have no evidence to lead me to believe it's
anything but a software bug on my part, but I've yet to track it down.
After this first hang, everything /seems/ stable, again, in limited
testing.

Again, my primary goal of getting this out now is allowing other teams
who are doing power work to move ahead, and also get some of the trivial
fixes moved ahead now. If I had to guess, I'm betting "Implement a basic
PM interrupt handler" might cause some fuss. If we can get the patches
reviewed, retested, and merged - that would be great.

I have pushed this to my fdo bdw-rc6 branch again with the hope that
relevant parties may use the patch series for testing. This branch is
based upon the latest available nightly, with 2 workarounds from Ken.

git://people.freedesktop.org/~bwidawsk/drm-intel bdw-rc6

A quick summary:
1-4 Are cleanups
5 is a cleanup + bug fix
6-7 are small bug fixes
8 handler for all of the PM interrupts
9 is the simple "on switch"

Ben Widawsky (9):
  drm/i915: Clarify RC6 enabling
  drm/i915: Stop pretending VLV has rc6+
  drm/i915: Just print rc6 facts
  drm/i915/bdw: Use centralized rc6 info print
  drm/i915/bdw: Extract rp_state_caps logic
  drm/i915/bdw: Set initial rps freq to nominal
  drm/i915/bdw: RPS frequency bits are the same as HSW
  drm/i915/bdw: Implement a basic PM interrupt handler
  drm/i915/bdw: Enable RC6

 drivers/gpu/drm/i915/i915_irq.c  | 80 +++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_drv.h |  2 +
 drivers/gpu/drm/i915/intel_pm.c  | 91 +++++++++++++++++++++++++++-------------
 4 files changed, 141 insertions(+), 33 deletions(-)

-- 
1.8.5.3

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

* [PATCH 1/9] drm/i915: Clarify RC6 enabling
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-02-06 13:38   ` Rodrigo Vivi
                     ` (2 more replies)
  2014-01-29  4:25 ` [PATCH 2/9] drm/i915: Stop pretending VLV has rc6+ Ben Widawsky
                   ` (8 subsequent siblings)
  9 siblings, 3 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

At one time, we though all future platforms would have the deeper RC6
states. As it turned out, they killed it after Ivybridge, and began
using other means to achieve the power savings (the stuff we need to get
to PC7+).

The enable function was left in a weird state of odd corner cases as a
result. Since the future is now, and we also have some insight into
what's currently the future, we have an opportunity to simplify, and
future proof the function.

NOTE: VLV will be addressed in a subsequent patch. This patch was trying
not to change functionality.

NOTE2: All callers sanitize the return value anyway, so this patch is
simply to have the code make a bit more sense.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 53d64bb..bcbdac2 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3161,14 +3161,10 @@ int intel_enable_rc6(const struct drm_device *dev)
 	if (INTEL_INFO(dev)->gen == 5)
 		return 0;
 
-	if (IS_HASWELL(dev))
-		return INTEL_RC6_ENABLE;
-
-	/* snb/ivb have more than one rc6 state. */
-	if (INTEL_INFO(dev)->gen == 6)
+	if (IS_IVYBRIDGE(dev) || IS_VALLEYVIEW(dev))
+		return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
+	else
 		return INTEL_RC6_ENABLE;
-
-	return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
 }
 
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
-- 
1.8.5.3

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

* [PATCH 2/9] drm/i915: Stop pretending VLV has rc6+
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
  2014-01-29  4:25 ` [PATCH 1/9] drm/i915: Clarify RC6 enabling Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-02-06 13:39   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuXxFqRixpPSeOpi=1t2sL=sVfmjdMR445dEQBozg1Z43w@mail.gmail.com>
  2014-01-29  4:25 ` [PATCH 3/9] drm/i915: Just print rc6 facts Ben Widawsky
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

It wasn't ever used by the caller anyway with the exception of what we
show in sysfs.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 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 bcbdac2..258241b 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3161,7 +3161,7 @@ int intel_enable_rc6(const struct drm_device *dev)
 	if (INTEL_INFO(dev)->gen == 5)
 		return 0;
 
-	if (IS_IVYBRIDGE(dev) || IS_VALLEYVIEW(dev))
+	if (IS_IVYBRIDGE(dev))
 		return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
 	else
 		return INTEL_RC6_ENABLE;
-- 
1.8.5.3

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

* [PATCH 3/9] drm/i915: Just print rc6 facts
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
  2014-01-29  4:25 ` [PATCH 1/9] drm/i915: Clarify RC6 enabling Ben Widawsky
  2014-01-29  4:25 ` [PATCH 2/9] drm/i915: Stop pretending VLV has rc6+ Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-02-06 13:41   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuW+_5n=zfDSf_F1aT+v7xzdm_GwUxKC5t8g6_LVCX6X_g@mail.gmail.com>
  2014-01-29  4:25 ` [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print Ben Widawsky
                   ` (6 subsequent siblings)
  9 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

Everything can be overridden by module parameters, so don't confuse the
users that are using them.

We have RC6 turned on for all platforms which support it, but Ironlake,
so the need to explain the situation is no longer pressing.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 258241b..944b99c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3135,16 +3135,10 @@ static void valleyview_disable_rps(struct drm_device *dev)
 
 static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
 {
-	if (IS_GEN6(dev))
-		DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
-
-	if (IS_HASWELL(dev))
-		DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
-
 	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",
-			(mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
+		 (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
+		 (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
+		 (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
 }
 
 int intel_enable_rc6(const struct drm_device *dev)
-- 
1.8.5.3

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

* [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
                   ` (2 preceding siblings ...)
  2014-01-29  4:25 ` [PATCH 3/9] drm/i915: Just print rc6 facts Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-02-06 13:42   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuVu0vvQNFKt2FhVf9CrXQa47WAfaqWP2EHp=mBMgExTkQ@mail.gmail.com>
  2014-01-29  4:25 ` [PATCH 5/9] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 944b99c..6acb429 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3215,10 +3215,10 @@ static void gen8_enable_rps(struct drm_device *dev)
 	/* 3: Enable RC6 */
 	if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
 		rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
-	DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
+	intel_print_rc6_info(dev, rc6_mask);
 	I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
-			GEN6_RC_CTL_EI_MODE(1) |
-			rc6_mask);
+				    GEN6_RC_CTL_EI_MODE(1) |
+				    rc6_mask);
 
 	/* 4 Program defaults and thresholds for RPS*/
 	I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
-- 
1.8.5.3

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

* [PATCH 5/9] drm/i915/bdw: Extract rp_state_caps logic
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
                   ` (3 preceding siblings ...)
  2014-01-29  4:25 ` [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-01-29  4:25 ` [PATCH 5/9] drm/i915/bdw: Set rp_state_caps Ben Widawsky
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

We have a need for duplicated parsing of the RP_STATE_CAPS register (and
the setting of the associated fields). To reuse some code, we can
extract the function into a simple helper.

This patch also addresses the fact that we missed doing this for gen8,
something we should have done anyway.

This could be two patches, one to extract, and one to add gen8, but it's
trivial enough that I think one is fine. I will accept a request to
split it.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6acb429..ae59bd9 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3184,6 +3184,17 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev)
 	I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs);
 }
 
+static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_cap)
+{
+	/* In units of 50MHz */
+	dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
+	dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
+	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
+	dev_priv->rps.cur_delay = 0;
+}
+
 static void gen8_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3202,6 +3213,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* 2b: Program RC6 thresholds.*/
 	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
@@ -3288,13 +3300,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
-	/* In units of 50MHz */
-	dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
-	dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
-	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
-	dev_priv->rps.cur_delay = 0;
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
-- 
1.8.5.3

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

* [PATCH 5/9] drm/i915/bdw: Set rp_state_caps
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
                   ` (4 preceding siblings ...)
  2014-01-29  4:25 ` [PATCH 5/9] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-02-06 13:45   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuUqCUM-2-yxCbPcCZ53yTxN+8Q5+syiAXqa86Vp47T70A@mail.gmail.com>
  2014-01-29  4:25 ` [PATCH 6/9] drm/i915/bdw: Set initial rps freq to nominal Ben Widawsky
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6acb429..ae59bd9 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3184,6 +3184,17 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev)
 	I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs);
 }
 
+static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_cap)
+{
+	/* In units of 50MHz */
+	dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
+	dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
+	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
+	dev_priv->rps.cur_delay = 0;
+}
+
 static void gen8_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3202,6 +3213,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* 2b: Program RC6 thresholds.*/
 	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
@@ -3288,13 +3300,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
-	/* In units of 50MHz */
-	dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
-	dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
-	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
-	dev_priv->rps.cur_delay = 0;
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
-- 
1.8.5.3

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

* [PATCH 6/9] drm/i915/bdw: Set initial rps freq to nominal
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
                   ` (5 preceding siblings ...)
  2014-01-29  4:25 ` [PATCH 5/9] drm/i915/bdw: Set rp_state_caps Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-01-29  4:25 ` [PATCH 7/9] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

Programming it outside of the rp0-rp1 range is considered a programming
error. Since we do not know that the previous value would actually be in
the range, program something we've read from the hardware, and therefore
know will work.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ae59bd9..34cc898 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3233,8 +3233,8 @@ static void gen8_enable_rps(struct drm_device *dev)
 				    rc6_mask);
 
 	/* 4 Program defaults and thresholds for RPS*/
-	I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
-	I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(12)); /* Request 600 MHz */
+	I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(dev_priv->rps.rp1_delay)); /* Request nominal */
+	I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(dev_priv->rps.rp1_delay));
 	/* NB: Docs say 1s, and 1000000 - which aren't equivalent */
 	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */
 
-- 
1.8.5.3

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

* [PATCH 7/9] drm/i915/bdw: RPS frequency bits are the same as HSW
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
                   ` (6 preceding siblings ...)
  2014-01-29  4:25 ` [PATCH 6/9] drm/i915/bdw: Set initial rps freq to nominal Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-02-06 13:52   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuU8bnYppf7D5k39QuuDkbHCUVznuVHzvd2dW1mDN0GpBA@mail.gmail.com>
  2014-01-29  4:25 ` [PATCH 8/9] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
  2014-01-29  4:25 ` [PATCH 9/9] drm/i915/bdw: Enable RC6 Ben Widawsky
  9 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 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 34cc898..deaaaf2 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3016,7 +3016,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 
 	gen6_set_rps_thresholds(dev_priv, val);
 
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		I915_WRITE(GEN6_RPNSWREQ,
 			   HSW_FREQUENCY(val));
 	else
-- 
1.8.5.3

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

* [PATCH 8/9] drm/i915/bdw: Implement a basic PM interrupt handler
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
                   ` (7 preceding siblings ...)
  2014-01-29  4:25 ` [PATCH 7/9] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-02-06 14:15   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuXYmUmGM2tDGO6KCT9Q1V6znbAwQf5OoC27++078bvfRg@mail.gmail.com>
  2014-01-29  4:25 ` [PATCH 9/9] drm/i915/bdw: Enable RC6 Ben Widawsky
  9 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

Almost all of it is reusable from the existing code. The primary
difference is we need to do even less in the interrupt handler, since
interrupts are not shared in the same way.

The patch is mostly a copy-paste of the existing snb+ code, with updates
to the relevant parts requiring changes to the interrupt handling. As
such it /should/ be relatively trivial. It's highly likely that I missed
some places where I need a gen8 version of the PM interrupts, but it has
become invisible to me by now.

This patch could probably be split into adding the new functions,
followed by actually handling the interrupts. Since the code is
currently disabled (and broken) I think the patch stands better by
itself.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_irq.c  | 80 ++++++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_drv.h |  2 +
 drivers/gpu/drm/i915/intel_pm.c  | 39 +++++++++++++++++++-
 4 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 72ade87..ab0c7ac 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -214,6 +214,53 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
 	return true;
 }
 
+/**
+  * bdw_update_pm_irq - update GT interrupt 2
+  * @dev_priv: driver private
+  * @interrupt_mask: mask of interrupt bits to update
+  * @enabled_irq_mask: mask of interrupt bits to enable
+  *
+  * Copied from the snb function, updated with relevant register offsets
+  */
+static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
+			      uint32_t interrupt_mask,
+			      uint32_t enabled_irq_mask)
+{
+	uint32_t new_val;
+
+	assert_spin_locked(&dev_priv->irq_lock);
+
+	if (dev_priv->pc8.irqs_disabled) {
+		WARN(1, "IRQs disabled\n");
+		dev_priv->pc8.regsave.gen6_pmimr &= ~interrupt_mask;
+		dev_priv->pc8.regsave.gen6_pmimr |= (~enabled_irq_mask &
+						     interrupt_mask);
+		return;
+	}
+
+	new_val = dev_priv->pm_irq_mask;
+	new_val &= ~interrupt_mask;
+	new_val |= (~enabled_irq_mask & interrupt_mask);
+
+	if (new_val != dev_priv->pm_irq_mask) {
+		dev_priv->pm_irq_mask = new_val;
+		I915_WRITE(GEN8_GT_IMR(2), I915_READ(GEN8_GT_IMR(2)) |
+					   dev_priv->pm_irq_mask);
+		POSTING_READ(GEN8_GT_IMR(2));
+	}
+}
+
+void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+{
+	bdw_update_pm_irq(dev_priv, mask, mask);
+}
+
+void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+{
+	bdw_update_pm_irq(dev_priv, mask, 0);
+}
+
+
 static bool cpt_can_enable_serr_int(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -997,11 +1044,15 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	pm_iir = dev_priv->rps.pm_iir;
 	dev_priv->rps.pm_iir = 0;
 	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
-	snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	if (IS_BROADWELL(dev_priv->dev))
+		bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	else {
+		/* Make sure we didn't queue anything we're not going to process. */
+		snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+		WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
+	}
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	/* Make sure we didn't queue anything we're not going to process. */
-	WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
 
 	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
 		return;
@@ -1192,6 +1243,19 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 		ivybridge_parity_error_irq_handler(dev, gt_iir);
 }
 
+static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
+{
+	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
+		return;
+
+	spin_lock(&dev_priv->irq_lock);
+	dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
+	bdw_disable_pm_irq(dev_priv, pm_iir & GEN6_PM_RPS_EVENTS);
+	spin_unlock(&dev_priv->irq_lock);
+
+	queue_work(dev_priv->wq, &dev_priv->rps.work);
+}
+
 static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
 				       struct drm_i915_private *dev_priv,
 				       u32 master_ctl)
@@ -1227,6 +1291,16 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
 			DRM_ERROR("The master control interrupt lied (GT1)!\n");
 	}
 
+	if (master_ctl & GEN8_GT_PM_IRQ) {
+		tmp = I915_READ(GEN8_GT_IIR(2));
+		if (tmp & GEN6_PM_RPS_EVENTS) {
+			ret = IRQ_HANDLED;
+			gen8_rps_irq_handler(dev_priv, tmp);
+			I915_WRITE(GEN8_GT_IIR(1), tmp & GEN6_PM_RPS_EVENTS);
+		} else
+			DRM_ERROR("The master control interrupt lied (PM)!\n");
+	}
+
 	if (master_ctl & GEN8_GT_VECS_IRQ) {
 		tmp = I915_READ(GEN8_GT_IIR(3));
 		if (tmp) {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index d77720e..f9e582e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4024,6 +4024,7 @@
 #define  GEN8_DE_PIPE_A_IRQ		(1<<16)
 #define  GEN8_DE_PIPE_IRQ(pipe)		(1<<(16+pipe))
 #define  GEN8_GT_VECS_IRQ		(1<<6)
+#define  GEN8_GT_PM_IRQ			(1<<4)
 #define  GEN8_GT_VCS2_IRQ		(1<<3)
 #define  GEN8_GT_VCS1_IRQ		(1<<2)
 #define  GEN8_GT_BCS_IRQ		(1<<1)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 44067bc..7b49779 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -608,6 +608,8 @@ void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void hsw_pc8_disable_interrupts(struct drm_device *dev);
 void hsw_pc8_restore_interrupts(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index deaaaf2..a5c9142 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3091,6 +3091,25 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
 
+static void gen8_disable_rps_interrupts(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+	I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) &
+				   ~GEN6_PM_RPS_EVENTS);
+	/* Complete PM interrupt masking here doesn't race with the rps work
+	 * item again unmasking PM interrupts because that is using a different
+	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
+
+	spin_lock_irq(&dev_priv->irq_lock);
+	dev_priv->rps.pm_iir = 0;
+	spin_unlock_irq(&dev_priv->irq_lock);
+
+	I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
+}
+
 static void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3116,7 +3135,10 @@ static void gen6_disable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
 
-	gen6_disable_rps_interrupts(dev);
+	if (IS_BROADWELL(dev))
+		gen8_disable_rps_interrupts(dev);
+	else
+		gen6_disable_rps_interrupts(dev);
 }
 
 static void valleyview_disable_rps(struct drm_device *dev)
@@ -3161,6 +3183,19 @@ int intel_enable_rc6(const struct drm_device *dev)
 		return INTEL_RC6_ENABLE;
 }
 
+static void gen8_enable_rps_interrupts(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	spin_lock_irq(&dev_priv->irq_lock);
+	WARN_ON(dev_priv->rps.pm_iir);
+	bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
+	spin_unlock_irq(&dev_priv->irq_lock);
+
+	I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
+}
+
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3263,7 +3298,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
 	gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
 
-	gen6_enable_rps_interrupts(dev);
+	gen8_enable_rps_interrupts(dev);
 
 	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
-- 
1.8.5.3

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

* [PATCH 9/9] drm/i915/bdw: Enable RC6
  2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
                   ` (8 preceding siblings ...)
  2014-01-29  4:25 ` [PATCH 8/9] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
@ 2014-01-29  4:25 ` Ben Widawsky
  2014-02-06 13:54   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuW-f4xdojasEP3wkSoVH3W1NJNdPACafgnPfVujFe4fjw@mail.gmail.com>
  9 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-01-29  4:25 UTC (permalink / raw)
  To: Intel GFX, intel-gfx; +Cc: Ben Widawsky, Ben Widawsky

It is tested and looking fairly stable now, so turn it on. It wasn't
intentionally turned off originally :P

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 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 a5c9142..377bd7f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4428,7 +4428,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		ironlake_enable_drps(dev);
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(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
-- 
1.8.5.3

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

* Re: [PATCH 1/9] drm/i915: Clarify RC6 enabling
  2014-01-29  4:25 ` [PATCH 1/9] drm/i915: Clarify RC6 enabling Ben Widawsky
@ 2014-02-06 13:38   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuUmDmAC9Nuu3DWYO2kU+Q5kyHyxSmF4rjADaY1iY6=RaQ@mail.gmail.com>
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
  2 siblings, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2014-02-06 13:38 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
<benjamin.widawsky@intel.com> wrote:
> At one time, we though all future platforms would have the deeper RC6
> states. As it turned out, they killed it after Ivybridge, and began
> using other means to achieve the power savings (the stuff we need to get
> to PC7+).
>
> The enable function was left in a weird state of odd corner cases as a
> result. Since the future is now, and we also have some insight into
> what's currently the future, we have an opportunity to simplify, and
> future proof the function.
>
> NOTE: VLV will be addressed in a subsequent patch. This patch was trying
> not to change functionality.
>
> NOTE2: All callers sanitize the return value anyway, so this patch is
> simply to have the code make a bit more sense.
>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 10 +++-------
>  1 file changed, 3 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 53d64bb..bcbdac2 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3161,14 +3161,10 @@ int intel_enable_rc6(const struct drm_device *dev)
>         if (INTEL_INFO(dev)->gen == 5)
>                 return 0;
>
> -       if (IS_HASWELL(dev))
> -               return INTEL_RC6_ENABLE;
> -
> -       /* snb/ivb have more than one rc6 state. */
> -       if (INTEL_INFO(dev)->gen == 6)
> +       if (IS_IVYBRIDGE(dev) || IS_VALLEYVIEW(dev))
> +               return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
> +       else
>                 return INTEL_RC6_ENABLE;
> -
> -       return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
>  }
>
>  static void gen6_enable_rps_interrupts(struct drm_device *dev)
> --
> 1.8.5.3
>
> _______________________________________________
> 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] 97+ messages in thread

* Re: [PATCH 2/9] drm/i915: Stop pretending VLV has rc6+
  2014-01-29  4:25 ` [PATCH 2/9] drm/i915: Stop pretending VLV has rc6+ Ben Widawsky
@ 2014-02-06 13:39   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuXxFqRixpPSeOpi=1t2sL=sVfmjdMR445dEQBozg1Z43w@mail.gmail.com>
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2014-02-06 13:39 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

hehehe I liked the title! :)

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
<benjamin.widawsky@intel.com> wrote:
> It wasn't ever used by the caller anyway with the exception of what we
> show in sysfs.
>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  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 bcbdac2..258241b 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3161,7 +3161,7 @@ int intel_enable_rc6(const struct drm_device *dev)
>         if (INTEL_INFO(dev)->gen == 5)
>                 return 0;
>
> -       if (IS_IVYBRIDGE(dev) || IS_VALLEYVIEW(dev))
> +       if (IS_IVYBRIDGE(dev))
>                 return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
>         else
>                 return INTEL_RC6_ENABLE;
> --
> 1.8.5.3
>
> _______________________________________________
> 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] 97+ messages in thread

* Re: [PATCH 3/9] drm/i915: Just print rc6 facts
  2014-01-29  4:25 ` [PATCH 3/9] drm/i915: Just print rc6 facts Ben Widawsky
@ 2014-02-06 13:41   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuW+_5n=zfDSf_F1aT+v7xzdm_GwUxKC5t8g6_LVCX6X_g@mail.gmail.com>
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2014-02-06 13:41 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
<benjamin.widawsky@intel.com> wrote:
> Everything can be overridden by module parameters, so don't confuse the
> users that are using them.
>
> We have RC6 turned on for all platforms which support it, but Ironlake,
> so the need to explain the situation is no longer pressing.
>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 12 +++---------
>  1 file changed, 3 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 258241b..944b99c 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3135,16 +3135,10 @@ static void valleyview_disable_rps(struct drm_device *dev)
>
>  static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
>  {
> -       if (IS_GEN6(dev))
> -               DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
> -
> -       if (IS_HASWELL(dev))
> -               DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
> -
>         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",
> -                       (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
> +                (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
> +                (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
> +                (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
>  }
>
>  int intel_enable_rc6(const struct drm_device *dev)
> --
> 1.8.5.3
>
> _______________________________________________
> 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] 97+ messages in thread

* Re: [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print
  2014-01-29  4:25 ` [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print Ben Widawsky
@ 2014-02-06 13:42   ` Rodrigo Vivi
  2014-02-11 16:12     ` Daniel Vetter
       [not found]   ` <CAOh5HuVu0vvQNFKt2FhVf9CrXQa47WAfaqWP2EHp=mBMgExTkQ@mail.gmail.com>
  1 sibling, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2014-02-06 13:42 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
<benjamin.widawsky@intel.com> wrote:
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 944b99c..6acb429 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3215,10 +3215,10 @@ static void gen8_enable_rps(struct drm_device *dev)
>         /* 3: Enable RC6 */
>         if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
>                 rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
> -       DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
> +       intel_print_rc6_info(dev, rc6_mask);
>         I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
> -                       GEN6_RC_CTL_EI_MODE(1) |
> -                       rc6_mask);
> +                                   GEN6_RC_CTL_EI_MODE(1) |
> +                                   rc6_mask);
>
>         /* 4 Program defaults and thresholds for RPS*/
>         I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
> --
> 1.8.5.3
>
> _______________________________________________
> 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] 97+ messages in thread

* Re: [PATCH 5/9] drm/i915/bdw: Set rp_state_caps
  2014-01-29  4:25 ` [PATCH 5/9] drm/i915/bdw: Set rp_state_caps Ben Widawsky
@ 2014-02-06 13:45   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuUqCUM-2-yxCbPcCZ53yTxN+8Q5+syiAXqa86Vp47T70A@mail.gmail.com>
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2014-02-06 13:45 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
<benjamin.widawsky@intel.com> wrote:
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 6acb429..ae59bd9 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3184,6 +3184,17 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev)
>         I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs);
>  }
>
> +static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_cap)

line over 80, but meh
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

> +{
> +       /* In units of 50MHz */
> +       dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
> +       dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
> +       dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
> +       dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
> +       dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
> +       dev_priv->rps.cur_delay = 0;
> +}
> +
>  static void gen8_enable_rps(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3202,6 +3213,7 @@ static void gen8_enable_rps(struct drm_device *dev)
>         I915_WRITE(GEN6_RC_CONTROL, 0);
>
>         rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
> +       parse_rp_state_cap(dev_priv, rp_state_cap);
>
>         /* 2b: Program RC6 thresholds.*/
>         I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
> @@ -3288,13 +3300,7 @@ static void gen6_enable_rps(struct drm_device *dev)
>         rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
>         gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
>
> -       /* In units of 50MHz */
> -       dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
> -       dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
> -       dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
> -       dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
> -       dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
> -       dev_priv->rps.cur_delay = 0;
> +       parse_rp_state_cap(dev_priv, rp_state_cap);
>
>         /* disable the counters and set deterministic thresholds */
>         I915_WRITE(GEN6_RC_CONTROL, 0);
> --
> 1.8.5.3
>
> _______________________________________________
> 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] 97+ messages in thread

* Re: [PATCH 7/9] drm/i915/bdw: RPS frequency bits are the same as HSW
  2014-01-29  4:25 ` [PATCH 7/9] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
@ 2014-02-06 13:52   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuU8bnYppf7D5k39QuuDkbHCUVznuVHzvd2dW1mDN0GpBA@mail.gmail.com>
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2014-02-06 13:52 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
<benjamin.widawsky@intel.com> wrote:
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  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 34cc898..deaaaf2 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3016,7 +3016,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
>
>         gen6_set_rps_thresholds(dev_priv, val);
>
> -       if (IS_HASWELL(dev))
> +       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>                 I915_WRITE(GEN6_RPNSWREQ,
>                            HSW_FREQUENCY(val));
>         else
> --
> 1.8.5.3
>
> _______________________________________________
> 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] 97+ messages in thread

* Re: [PATCH 9/9] drm/i915/bdw: Enable RC6
  2014-01-29  4:25 ` [PATCH 9/9] drm/i915/bdw: Enable RC6 Ben Widawsky
@ 2014-02-06 13:54   ` Rodrigo Vivi
  2014-02-17 20:04     ` Ben Widawsky
       [not found]   ` <CAOh5HuW-f4xdojasEP3wkSoVH3W1NJNdPACafgnPfVujFe4fjw@mail.gmail.com>
  1 sibling, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2014-02-06 13:54 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
<benjamin.widawsky@intel.com> wrote:
> It is tested and looking fairly stable now, so turn it on. It wasn't
> intentionally turned off originally :P
>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  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 a5c9142..377bd7f 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -4428,7 +4428,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
>                 ironlake_enable_drps(dev);
>                 ironlake_enable_rc6(dev);
>                 intel_init_emon(dev);
> -       } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
> +       } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {

why not IS_GEN8?
or why not use gen >= gen6?

anyway: Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

>                 /*
>                  * PCU communication is slow and this doesn't need to be
>                  * done at any specific time, so do this out of our fast path
> --
> 1.8.5.3
>
> _______________________________________________
> 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] 97+ messages in thread

* Re: [PATCH 8/9] drm/i915/bdw: Implement a basic PM interrupt handler
  2014-01-29  4:25 ` [PATCH 8/9] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
@ 2014-02-06 14:15   ` Rodrigo Vivi
  2014-02-17 20:01     ` Ben Widawsky
       [not found]   ` <CAOh5HuXYmUmGM2tDGO6KCT9Q1V6znbAwQf5OoC27++078bvfRg@mail.gmail.com>
  1 sibling, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2014-02-06 14:15 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
<benjamin.widawsky@intel.com> wrote:
> Almost all of it is reusable from the existing code. The primary
> difference is we need to do even less in the interrupt handler, since
> interrupts are not shared in the same way.
>
> The patch is mostly a copy-paste of the existing snb+ code, with updates
> to the relevant parts requiring changes to the interrupt handling. As
> such it /should/ be relatively trivial. It's highly likely that I missed
> some places where I need a gen8 version of the PM interrupts, but it has
> become invisible to me by now.
>
> This patch could probably be split into adding the new functions,
> followed by actually handling the interrupts. Since the code is
> currently disabled (and broken) I think the patch stands better by
> itself.
>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/i915_irq.c  | 80 ++++++++++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/i915_reg.h  |  1 +
>  drivers/gpu/drm/i915/intel_drv.h |  2 +
>  drivers/gpu/drm/i915/intel_pm.c  | 39 +++++++++++++++++++-
>  4 files changed, 117 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 72ade87..ab0c7ac 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -214,6 +214,53 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
>         return true;
>  }
>
> +/**
> +  * bdw_update_pm_irq - update GT interrupt 2
> +  * @dev_priv: driver private
> +  * @interrupt_mask: mask of interrupt bits to update
> +  * @enabled_irq_mask: mask of interrupt bits to enable
> +  *
> +  * Copied from the snb function, updated with relevant register offsets
> +  */
> +static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
> +                             uint32_t interrupt_mask,
> +                             uint32_t enabled_irq_mask)
> +{
> +       uint32_t new_val;
> +
> +       assert_spin_locked(&dev_priv->irq_lock);
> +
> +       if (dev_priv->pc8.irqs_disabled) {
> +               WARN(1, "IRQs disabled\n");
> +               dev_priv->pc8.regsave.gen6_pmimr &= ~interrupt_mask;
> +               dev_priv->pc8.regsave.gen6_pmimr |= (~enabled_irq_mask &
> +                                                    interrupt_mask);
> +               return;
> +       }
> +
> +       new_val = dev_priv->pm_irq_mask;
> +       new_val &= ~interrupt_mask;
> +       new_val |= (~enabled_irq_mask & interrupt_mask);
> +
> +       if (new_val != dev_priv->pm_irq_mask) {
> +               dev_priv->pm_irq_mask = new_val;
> +               I915_WRITE(GEN8_GT_IMR(2), I915_READ(GEN8_GT_IMR(2)) |
> +                                          dev_priv->pm_irq_mask);
> +               POSTING_READ(GEN8_GT_IMR(2));
> +       }
> +}
> +
> +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
> +{
> +       bdw_update_pm_irq(dev_priv, mask, mask);
> +}
> +
> +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
> +{
> +       bdw_update_pm_irq(dev_priv, mask, 0);
> +}
> +
> +
>  static bool cpt_can_enable_serr_int(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -997,11 +1044,15 @@ static void gen6_pm_rps_work(struct work_struct *work)
>         pm_iir = dev_priv->rps.pm_iir;
>         dev_priv->rps.pm_iir = 0;
>         /* Make sure not to corrupt PMIMR state used by ringbuffer code */
> -       snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> +       if (IS_BROADWELL(dev_priv->dev))
> +               bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> +       else {
> +               /* Make sure we didn't queue anything we're not going to process. */
> +               snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);

inverted lines since comment sounds to be related to above line.

> +               WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
> +       }
>         spin_unlock_irq(&dev_priv->irq_lock);
>
> -       /* Make sure we didn't queue anything we're not going to process. */
> -       WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
>
>         if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
>                 return;
> @@ -1192,6 +1243,19 @@ static void snb_gt_irq_handler(struct drm_device *dev,
>                 ivybridge_parity_error_irq_handler(dev, gt_iir);
>  }
>
> +static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
> +{
> +       if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
> +               return;
> +
> +       spin_lock(&dev_priv->irq_lock);
> +       dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
> +       bdw_disable_pm_irq(dev_priv, pm_iir & GEN6_PM_RPS_EVENTS);
> +       spin_unlock(&dev_priv->irq_lock);
> +
> +       queue_work(dev_priv->wq, &dev_priv->rps.work);

sorry if this is a stupid question, but don't we need the vebox part here?

> +}
> +
>  static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
>                                        struct drm_i915_private *dev_priv,
>                                        u32 master_ctl)
> @@ -1227,6 +1291,16 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
>                         DRM_ERROR("The master control interrupt lied (GT1)!\n");
>         }
>
> +       if (master_ctl & GEN8_GT_PM_IRQ) {
> +               tmp = I915_READ(GEN8_GT_IIR(2));
> +               if (tmp & GEN6_PM_RPS_EVENTS) {
> +                       ret = IRQ_HANDLED;
> +                       gen8_rps_irq_handler(dev_priv, tmp);
> +                       I915_WRITE(GEN8_GT_IIR(1), tmp & GEN6_PM_RPS_EVENTS);
> +               } else
> +                       DRM_ERROR("The master control interrupt lied (PM)!\n");
> +       }
> +
>         if (master_ctl & GEN8_GT_VECS_IRQ) {
>                 tmp = I915_READ(GEN8_GT_IIR(3));
>                 if (tmp) {
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index d77720e..f9e582e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4024,6 +4024,7 @@
>  #define  GEN8_DE_PIPE_A_IRQ            (1<<16)
>  #define  GEN8_DE_PIPE_IRQ(pipe)                (1<<(16+pipe))
>  #define  GEN8_GT_VECS_IRQ              (1<<6)
> +#define  GEN8_GT_PM_IRQ                        (1<<4)
>  #define  GEN8_GT_VCS2_IRQ              (1<<3)
>  #define  GEN8_GT_VCS1_IRQ              (1<<2)
>  #define  GEN8_GT_BCS_IRQ               (1<<1)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 44067bc..7b49779 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -608,6 +608,8 @@ void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void hsw_pc8_disable_interrupts(struct drm_device *dev);
>  void hsw_pc8_restore_interrupts(struct drm_device *dev);
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index deaaaf2..a5c9142 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3091,6 +3091,25 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
>         trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
>  }
>
> +static void gen8_disable_rps_interrupts(struct drm_device *dev)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
> +       I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) &
> +                                  ~GEN6_PM_RPS_EVENTS);
> +       /* Complete PM interrupt masking here doesn't race with the rps work
> +        * item again unmasking PM interrupts because that is using a different
> +        * register (PMIMR) to mask PM interrupts. The only risk is in leaving
> +        * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
> +
> +       spin_lock_irq(&dev_priv->irq_lock);
> +       dev_priv->rps.pm_iir = 0;
> +       spin_unlock_irq(&dev_priv->irq_lock);
> +
> +       I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
> +}
> +
>  static void gen6_disable_rps_interrupts(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3116,7 +3135,10 @@ static void gen6_disable_rps(struct drm_device *dev)
>         I915_WRITE(GEN6_RC_CONTROL, 0);
>         I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
>
> -       gen6_disable_rps_interrupts(dev);
> +       if (IS_BROADWELL(dev))
> +               gen8_disable_rps_interrupts(dev);
> +       else
> +               gen6_disable_rps_interrupts(dev);
>  }
>
>  static void valleyview_disable_rps(struct drm_device *dev)
> @@ -3161,6 +3183,19 @@ int intel_enable_rc6(const struct drm_device *dev)
>                 return INTEL_RC6_ENABLE;
>  }
>
> +static void gen8_enable_rps_interrupts(struct drm_device *dev)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       spin_lock_irq(&dev_priv->irq_lock);
> +       WARN_ON(dev_priv->rps.pm_iir);
> +       bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> +       I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
> +       spin_unlock_irq(&dev_priv->irq_lock);
> +
> +       I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
> +}
> +
>  static void gen6_enable_rps_interrupts(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3263,7 +3298,7 @@ static void gen8_enable_rps(struct drm_device *dev)
>
>         gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
>
> -       gen6_enable_rps_interrupts(dev);
> +       gen8_enable_rps_interrupts(dev);
>
>         gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>  }
> --
> 1.8.5.3
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

with those explained or fixed feel free to use:

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

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

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

* Re: [PATCH 1/9] drm/i915: Clarify RC6 enabling
       [not found]   ` <CAOh5HuUmDmAC9Nuu3DWYO2kU+Q5kyHyxSmF4rjADaY1iY6=RaQ@mail.gmail.com>
@ 2014-02-07  5:30     ` S, Deepak
  0 siblings, 0 replies; 97+ messages in thread
From: S, Deepak @ 2014-02-07  5:30 UTC (permalink / raw)
  To: intel-gfx


On Wed, Jan 29, 2014 at 9:55 AM, Ben Widawsky
> <benjamin.widawsky@intel.com <mailto:benjamin.widawsky@intel.com>> wrote:
>
>     At one time, we though all future platforms would have the deeper RC6
>     states. As it turned out, they killed it after Ivybridge, and began
>     using other means to achieve the power savings (the stuff we need to get
>     to PC7+).
>
>     The enable function was left in a weird state of odd corner cases as a
>     result. Since the future is now, and we also have some insight into
>     what's currently the future, we have an opportunity to simplify, and
>     future proof the function.
>
>     NOTE: VLV will be addressed in a subsequent patch. This patch was trying
>     not to change functionality.
>
>     NOTE2: All callers sanitize the return value anyway, so this patch is
>     simply to have the code make a bit more sense.
>
>     Signed-off-by: Ben Widawsky <ben@bwidawsk.net <mailto:ben@bwidawsk.net>>
>     ---
>       drivers/gpu/drm/i915/intel_pm.c | 10 +++-------
>       1 file changed, 3 insertions(+), 7 deletions(-)
>
>     diff --git a/drivers/gpu/drm/i915/intel_pm.c
>     b/drivers/gpu/drm/i915/intel_pm.c
>     index 53d64bb..bcbdac2 100644
>     --- a/drivers/gpu/drm/i915/intel_pm.c
>     +++ b/drivers/gpu/drm/i915/intel_pm.c
>     @@ -3161,14 +3161,10 @@ int intel_enable_rc6(const struct drm_device
>     *dev)
>              if (INTEL_INFO(dev)->gen == 5)
>                      return 0;
>
>     -       if (IS_HASWELL(dev))
>     -               return INTEL_RC6_ENABLE;
>     -
>     -       /* snb/ivb have more than one rc6 state. */
>     -       if (INTEL_INFO(dev)->gen == 6)
>     +       if (IS_IVYBRIDGE(dev) || IS_VALLEYVIEW(dev))
>     +               return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
>     +       else
>                      return INTEL_RC6_ENABLE;
>     -
>     -       return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
>       }
>
>       static void gen6_enable_rps_interrupts(struct drm_device *dev)
>     --
>     1.8.5.3
>
>     _______________________________________________
>     Intel-gfx mailing list
>     Intel-gfx@lists.freedesktop.org <mailto:Intel-gfx@lists.freedesktop.org>
>     http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>

Reviewed-by: Deepak S <deepak.s@intel.com>

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

* Re: [PATCH 2/9] drm/i915: Stop pretending VLV has rc6+
       [not found]   ` <CAOh5HuXxFqRixpPSeOpi=1t2sL=sVfmjdMR445dEQBozg1Z43w@mail.gmail.com>
@ 2014-02-07  5:42     ` S, Deepak
  0 siblings, 0 replies; 97+ messages in thread
From: S, Deepak @ 2014-02-07  5:42 UTC (permalink / raw)
  To: benjamin.widawsky, intel-gfx



On Wed, Jan 29, 2014 at 9:55 AM, Ben Widawsky
> <benjamin.widawsky@intel.com <mailto:benjamin.widawsky@intel.com>> wrote:
>
>     It wasn't ever used by the caller anyway with the exception of what we
>     show in sysfs.
>
>     Signed-off-by: Ben Widawsky <ben@bwidawsk.net <mailto:ben@bwidawsk.net>>
>     ---
>       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 bcbdac2..258241b 100644
>     --- a/drivers/gpu/drm/i915/intel_pm.c
>     +++ b/drivers/gpu/drm/i915/intel_pm.c
>     @@ -3161,7 +3161,7 @@ int intel_enable_rc6(const struct drm_device *dev)
>              if (INTEL_INFO(dev)->gen == 5)
>                      return 0;
>
>     -       if (IS_IVYBRIDGE(dev) || IS_VALLEYVIEW(dev))
>     +       if (IS_IVYBRIDGE(dev))
>                      return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
>              else
>                      return INTEL_RC6_ENABLE;
>     --
>     1.8.5.3
>
>     _______________________________________________
>     Intel-gfx mailing list
>     Intel-gfx@lists.freedesktop.org <mailto:Intel-gfx@lists.freedesktop.org>
>     http://lists.freedesktop.org/mailman/listinfo/intel-gfx

I think, we can avoid else condition and return INTEL_RC6_ENABLE if the 
other platform checks fails?

Reviewed-by: Deepak S <deepak.s@intel.com>

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

* Re: [PATCH 3/9] drm/i915: Just print rc6 facts
       [not found]   ` <CAOh5HuW+_5n=zfDSf_F1aT+v7xzdm_GwUxKC5t8g6_LVCX6X_g@mail.gmail.com>
@ 2014-02-07  5:44     ` S, Deepak
  0 siblings, 0 replies; 97+ messages in thread
From: S, Deepak @ 2014-02-07  5:44 UTC (permalink / raw)
  To: benjamin.widawsky, intel-gfx



On Wed, Jan 29, 2014 at 9:55 AM, Ben Widawsky
> <benjamin.widawsky@intel.com <mailto:benjamin.widawsky@intel.com>> wrote:
>
>     Everything can be overridden by module parameters, so don't confuse the
>     users that are using them.
>
>     We have RC6 turned on for all platforms which support it, but Ironlake,
>     so the need to explain the situation is no longer pressing.
>
>     Signed-off-by: Ben Widawsky <ben@bwidawsk.net <mailto:ben@bwidawsk.net>>
>     ---
>       drivers/gpu/drm/i915/intel_pm.c | 12 +++---------
>       1 file changed, 3 insertions(+), 9 deletions(-)
>
>     diff --git a/drivers/gpu/drm/i915/intel_pm.c
>     b/drivers/gpu/drm/i915/intel_pm.c
>     index 258241b..944b99c 100644
>     --- a/drivers/gpu/drm/i915/intel_pm.c
>     +++ b/drivers/gpu/drm/i915/intel_pm.c
>     @@ -3135,16 +3135,10 @@ static void valleyview_disable_rps(struct
>     drm_device *dev)
>
>       static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
>       {
>     -       if (IS_GEN6(dev))
>     -               DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
>     -
>     -       if (IS_HASWELL(dev))
>     -               DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
>     -
>              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",
>     -                       (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" :
>     "off");
>     +                (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
>     +                (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
>     +                (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
>       }
>
>       int intel_enable_rc6(const struct drm_device *dev)
>     --
>     1.8.5.3
>
>     _______________________________________________
>     Intel-gfx mailing list
>     Intel-gfx@lists.freedesktop.org <mailto:Intel-gfx@lists.freedesktop.org>
>     http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>

Reviewed-by: Deepak S <deepak.s@intel.com>

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

* Re: [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print
       [not found]   ` <CAOh5HuVu0vvQNFKt2FhVf9CrXQa47WAfaqWP2EHp=mBMgExTkQ@mail.gmail.com>
@ 2014-02-07  5:46     ` S, Deepak
  0 siblings, 0 replies; 97+ messages in thread
From: S, Deepak @ 2014-02-07  5:46 UTC (permalink / raw)
  To: benjamin.widawsky, intel-gfx


On Wed, Jan 29, 2014 at 9:55 AM, Ben Widawsky
> <benjamin.widawsky@intel.com <mailto:benjamin.widawsky@intel.com>> wrote:
>
>     Signed-off-by: Ben Widawsky <ben@bwidawsk.net <mailto:ben@bwidawsk.net>>
>     ---
>       drivers/gpu/drm/i915/intel_pm.c | 6 +++---
>       1 file changed, 3 insertions(+), 3 deletions(-)
>
>     diff --git a/drivers/gpu/drm/i915/intel_pm.c
>     b/drivers/gpu/drm/i915/intel_pm.c
>     index 944b99c..6acb429 100644
>     --- a/drivers/gpu/drm/i915/intel_pm.c
>     +++ b/drivers/gpu/drm/i915/intel_pm.c
>     @@ -3215,10 +3215,10 @@ static void gen8_enable_rps(struct
>     drm_device *dev)
>              /* 3: Enable RC6 */
>              if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
>                      rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
>     -       DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
>     "on" : "off");
>     +       intel_print_rc6_info(dev, rc6_mask);
>              I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
>     -                       GEN6_RC_CTL_EI_MODE(1) |
>     -                       rc6_mask);
>     +                                   GEN6_RC_CTL_EI_MODE(1) |
>     +                                   rc6_mask);
>
>              /* 4 Program defaults and thresholds for RPS*/
>              I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request
>     500 MHz */
>     --
>     1.8.5.3
>
>     _______________________________________________
>     Intel-gfx mailing list
>     Intel-gfx@lists.freedesktop.org <mailto:Intel-gfx@lists.freedesktop.org>
>     http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
Reviewed-by: Deepak S <deepak.s@intel.com>

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

* Re: [PATCH 5/9] drm/i915/bdw: Set rp_state_caps
       [not found]   ` <CAOh5HuUqCUM-2-yxCbPcCZ53yTxN+8Q5+syiAXqa86Vp47T70A@mail.gmail.com>
@ 2014-02-07  6:10     ` S, Deepak
  0 siblings, 0 replies; 97+ messages in thread
From: S, Deepak @ 2014-02-07  6:10 UTC (permalink / raw)
  To: benjamin.widawsky, intel-gfx


On Wed, Jan 29, 2014 at 9:55 AM, Ben Widawsky
> <benjamin.widawsky@intel.com <mailto:benjamin.widawsky@intel.com>> wrote:
>
>     Signed-off-by: Ben Widawsky <ben@bwidawsk.net <mailto:ben@bwidawsk.net>>
>     ---
>       drivers/gpu/drm/i915/intel_pm.c | 20 +++++++++++++-------
>       1 file changed, 13 insertions(+), 7 deletions(-)
>
>     diff --git a/drivers/gpu/drm/i915/intel_pm.c
>     b/drivers/gpu/drm/i915/intel_pm.c
>     index 6acb429..ae59bd9 100644
>     --- a/drivers/gpu/drm/i915/intel_pm.c
>     +++ b/drivers/gpu/drm/i915/intel_pm.c
>     @@ -3184,6 +3184,17 @@ static void gen6_enable_rps_interrupts(struct
>     drm_device *dev)
>              I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs);
>       }
>
>     +static void parse_rp_state_cap(struct drm_i915_private *dev_priv,
>     u32 rp_state_cap)
>     +{
>     +       /* In units of 50MHz */
>     +       dev_priv->rps.hw_max = dev_priv->rps.max_delay =
>     rp_state_cap & 0xff;
>     +       dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
>     +       dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
>     +       dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
>     +       dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
>     +       dev_priv->rps.cur_delay = 0;
>     +}
>     +
>       static void gen8_enable_rps(struct drm_device *dev)
>       {
>              struct drm_i915_private *dev_priv = dev->dev_private;
>     @@ -3202,6 +3213,7 @@ static void gen8_enable_rps(struct drm_device
>     *dev)
>              I915_WRITE(GEN6_RC_CONTROL, 0);
>
>              rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
>     +       parse_rp_state_cap(dev_priv, rp_state_cap);
>
>              /* 2b: Program RC6 thresholds.*/
>              I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
>     @@ -3288,13 +3300,7 @@ static void gen6_enable_rps(struct drm_device
>     *dev)
>              rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
>              gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
>
>     -       /* In units of 50MHz */
>     -       dev_priv->rps.hw_max = dev_priv->rps.max_delay =
>     rp_state_cap & 0xff;
>     -       dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff;
>     -       dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
>     -       dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
>     -       dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
>     -       dev_priv->rps.cur_delay = 0;
>     +       parse_rp_state_cap(dev_priv, rp_state_cap);
>
>              /* disable the counters and set deterministic thresholds */
>              I915_WRITE(GEN6_RC_CONTROL, 0);
>     --
>     1.8.5.3
>
>     _______________________________________________
>     Intel-gfx mailing list
>     Intel-gfx@lists.freedesktop.org <mailto:Intel-gfx@lists.freedesktop.org>
>     http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>

Looks fine
Reviewed-by: Deepak S <deepak.s@intel.com>

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

* Re: [PATCH 7/9] drm/i915/bdw: RPS frequency bits are the same as HSW
       [not found]   ` <CAOh5HuU8bnYppf7D5k39QuuDkbHCUVznuVHzvd2dW1mDN0GpBA@mail.gmail.com>
@ 2014-02-07  6:25     ` S, Deepak
  0 siblings, 0 replies; 97+ messages in thread
From: S, Deepak @ 2014-02-07  6:25 UTC (permalink / raw)
  To: benjamin.widawsky, intel-gfx

On Wed, Jan 29, 2014 at 9:55 AM, Ben Widawsky
> <benjamin.widawsky@intel.com <mailto:benjamin.widawsky@intel.com>> wrote:
>
>     Signed-off-by: Ben Widawsky <ben@bwidawsk.net <mailto:ben@bwidawsk.net>>
>     ---
>       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 34cc898..deaaaf2 100644
>     --- a/drivers/gpu/drm/i915/intel_pm.c
>     +++ b/drivers/gpu/drm/i915/intel_pm.c
>     @@ -3016,7 +3016,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
>
>              gen6_set_rps_thresholds(dev_priv, val);
>
>     -       if (IS_HASWELL(dev))
>     +       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>                      I915_WRITE(GEN6_RPNSWREQ,
>                                 HSW_FREQUENCY(val));
>              else
>     --
>     1.8.5.3
>
>     _______________________________________________
>     Intel-gfx mailing list
>     Intel-gfx@lists.freedesktop.org <mailto:Intel-gfx@lists.freedesktop.org>
>     http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Looks fine

Reviewed-by: Deepak S <deepak.s@intel.com>

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

* Re: [PATCH 8/9] drm/i915/bdw: Implement a basic PM interrupt handler
       [not found]   ` <CAOh5HuXYmUmGM2tDGO6KCT9Q1V6znbAwQf5OoC27++078bvfRg@mail.gmail.com>
@ 2014-02-07  6:43     ` S, Deepak
  0 siblings, 0 replies; 97+ messages in thread
From: S, Deepak @ 2014-02-07  6:43 UTC (permalink / raw)
  To: benjamin.widawsky, intel-gfx

On Wed, Jan 29, 2014 at 9:55 AM, Ben Widawsky
> <benjamin.widawsky@intel.com <mailto:benjamin.widawsky@intel.com>> wrote:
>
>     Almost all of it is reusable from the existing code. The primary
>     difference is we need to do even less in the interrupt handler, since
>     interrupts are not shared in the same way.
>
>     The patch is mostly a copy-paste of the existing snb+ code, with updates
>     to the relevant parts requiring changes to the interrupt handling. As
>     such it /should/ be relatively trivial. It's highly likely that I missed
>     some places where I need a gen8 version of the PM interrupts, but it has
>     become invisible to me by now.
>
>     This patch could probably be split into adding the new functions,
>     followed by actually handling the interrupts. Since the code is
>     currently disabled (and broken) I think the patch stands better by
>     itself.
>
>     Signed-off-by: Ben Widawsky <ben@bwidawsk.net <mailto:ben@bwidawsk.net>>
>     ---
>       drivers/gpu/drm/i915/i915_irq.c  | 80
>     ++++++++++++++++++++++++++++++++++++++--
>       drivers/gpu/drm/i915/i915_reg.h  |  1 +
>       drivers/gpu/drm/i915/intel_drv.h |  2 +
>       drivers/gpu/drm/i915/intel_pm.c  | 39 +++++++++++++++++++-
>       4 files changed, 117 insertions(+), 5 deletions(-)
>
>     diff --git a/drivers/gpu/drm/i915/i915_irq.c
>     b/drivers/gpu/drm/i915/i915_irq.c
>     index 72ade87..ab0c7ac 100644
>     --- a/drivers/gpu/drm/i915/i915_irq.c
>     +++ b/drivers/gpu/drm/i915/i915_irq.c
>     @@ -214,6 +214,53 @@ static bool ivb_can_enable_err_int(struct
>     drm_device *dev)
>              return true;
>       }
>
>     +/**
>     +  * bdw_update_pm_irq - update GT interrupt 2
>     +  * @dev_priv: driver private
>     +  * @interrupt_mask: mask of interrupt bits to update
>     +  * @enabled_irq_mask: mask of interrupt bits to enable
>     +  *
>     +  * Copied from the snb function, updated with relevant register
>     offsets
>     +  */
>     +static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
>     +                             uint32_t interrupt_mask,
>     +                             uint32_t enabled_irq_mask)
>     +{
>     +       uint32_t new_val;
>     +
>     +       assert_spin_locked(&dev_priv->irq_lock);
>     +
>     +       if (dev_priv->pc8.irqs_disabled) {
>     +               WARN(1, "IRQs disabled\n");
>     +               dev_priv->pc8.regsave.gen6_pmimr &= ~interrupt_mask;
>     +               dev_priv->pc8.regsave.gen6_pmimr |= (~enabled_irq_mask &
>     +                                                    interrupt_mask);
>     +               return;
>     +       }
>     +
>     +       new_val = dev_priv->pm_irq_mask;
>     +       new_val &= ~interrupt_mask;
>     +       new_val |= (~enabled_irq_mask & interrupt_mask);
>     +
>     +       if (new_val != dev_priv->pm_irq_mask) {
>     +               dev_priv->pm_irq_mask = new_val;
>     +               I915_WRITE(GEN8_GT_IMR(2), I915_READ(GEN8_GT_IMR(2)) |
>     +                                          dev_priv->pm_irq_mask);
>     +               POSTING_READ(GEN8_GT_IMR(2));
>     +       }
>     +}
>     +
>     +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t
>     mask)
>     +{
>     +       bdw_update_pm_irq(dev_priv, mask, mask);
>     +}
>     +
>     +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t
>     mask)
>     +{
>     +       bdw_update_pm_irq(dev_priv, mask, 0);
>     +}
>     +
>     +
>       static bool cpt_can_enable_serr_int(struct drm_device *dev)
>       {
>              struct drm_i915_private *dev_priv = dev->dev_private;
>     @@ -997,11 +1044,15 @@ static void gen6_pm_rps_work(struct
>     work_struct *work)
>              pm_iir = dev_priv->rps.pm_iir;
>              dev_priv->rps.pm_iir = 0;
>              /* Make sure not to corrupt PMIMR state used by ringbuffer
>     code */
>     -       snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
>     +       if (IS_BROADWELL(dev_priv->dev))
>     +               bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
>     +       else {
>     +               /* Make sure we didn't queue anything we're not
>     going to process. */
>     +               snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
>     +               WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
>     +       }
>              spin_unlock_irq(&dev_priv->irq_lock);
>
>     -       /* Make sure we didn't queue anything we're not going to
>     process. */
>     -       WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
>
>              if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
>                      return;
>     @@ -1192,6 +1243,19 @@ static void snb_gt_irq_handler(struct
>     drm_device *dev,
>                      ivybridge_parity_error_irq_handler(dev, gt_iir);
>       }
>
>     +static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv,
>     u32 pm_iir)
>     +{
>     +       if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
>     +               return;
>     +
>     +       spin_lock(&dev_priv->irq_lock);
>     +       dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
>     +       bdw_disable_pm_irq(dev_priv, pm_iir & GEN6_PM_RPS_EVENTS);
>     +       spin_unlock(&dev_priv->irq_lock);
>     +
>     +       queue_work(dev_priv->wq, &dev_priv->rps.work);
>     +}

We can use the "gen6_rps_irq_handler" right?

>       static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
>                                             struct drm_i915_private
>     *dev_priv,
>                                             u32 master_ctl)
>     @@ -1227,6 +1291,16 @@ static irqreturn_t gen8_gt_irq_handler(struct
>     drm_device *dev,
>                              DRM_ERROR("The master control interrupt
>     lied (GT1)!\n");
>              }
>
>     +       if (master_ctl & GEN8_GT_PM_IRQ) {
>     +               tmp = I915_READ(GEN8_GT_IIR(2));
>     +               if (tmp & GEN6_PM_RPS_EVENTS) {
>     +                       ret = IRQ_HANDLED;
>     +                       gen8_rps_irq_handler(dev_priv, tmp);
>     +                       I915_WRITE(GEN8_GT_IIR(1), tmp &
>     GEN6_PM_RPS_EVENTS);
>     +               } else
>     +                       DRM_ERROR("The master control interrupt lied
>     (PM)!\n");
>     +       }
>     +
>              if (master_ctl & GEN8_GT_VECS_IRQ) {
>                      tmp = I915_READ(GEN8_GT_IIR(3));
>                      if (tmp) {
>     diff --git a/drivers/gpu/drm/i915/i915_reg.h
>     b/drivers/gpu/drm/i915/i915_reg.h
>     index d77720e..f9e582e 100644
>     --- a/drivers/gpu/drm/i915/i915_reg.h
>     +++ b/drivers/gpu/drm/i915/i915_reg.h
>     @@ -4024,6 +4024,7 @@
>       #define  GEN8_DE_PIPE_A_IRQ            (1<<16)
>       #define  GEN8_DE_PIPE_IRQ(pipe)                (1<<(16+pipe))
>       #define  GEN8_GT_VECS_IRQ              (1<<6)
>     +#define  GEN8_GT_PM_IRQ                        (1<<4)
>       #define  GEN8_GT_VCS2_IRQ              (1<<3)
>       #define  GEN8_GT_VCS1_IRQ              (1<<2)
>       #define  GEN8_GT_BCS_IRQ               (1<<1)
>     diff --git a/drivers/gpu/drm/i915/intel_drv.h
>     b/drivers/gpu/drm/i915/intel_drv.h
>     index 44067bc..7b49779 100644
>     --- a/drivers/gpu/drm/i915/intel_drv.h
>     +++ b/drivers/gpu/drm/i915/intel_drv.h
>     @@ -608,6 +608,8 @@ void ilk_enable_gt_irq(struct drm_i915_private
>     *dev_priv, uint32_t mask);
>       void ilk_disable_gt_irq(struct drm_i915_private *dev_priv,
>     uint32_t mask);
>       void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t
>     mask);
>       void snb_disable_pm_irq(struct drm_i915_private *dev_priv,
>     uint32_t mask);
>     +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t
>     mask);
>     +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t
>     mask);
>       void hsw_pc8_disable_interrupts(struct drm_device *dev);
>       void hsw_pc8_restore_interrupts(struct drm_device *dev);
>
>     diff --git a/drivers/gpu/drm/i915/intel_pm.c
>     b/drivers/gpu/drm/i915/intel_pm.c
>     index deaaaf2..a5c9142 100644
>     --- a/drivers/gpu/drm/i915/intel_pm.c
>     +++ b/drivers/gpu/drm/i915/intel_pm.c
>     @@ -3091,6 +3091,25 @@ void valleyview_set_rps(struct drm_device
>     *dev, u8 val)
>              trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
>       }
>
>     +static void gen8_disable_rps_interrupts(struct drm_device *dev)
>     +{
>     +       struct drm_i915_private *dev_priv = dev->dev_private;
>     +
>     +       I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
>     +       I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) &
>     +                                  ~GEN6_PM_RPS_EVENTS);
>     +       /* Complete PM interrupt masking here doesn't race with the
>     rps work
>     +        * item again unmasking PM interrupts because that is using
>     a different
>     +        * register (PMIMR) to mask PM interrupts. The only risk is
>     in leaving
>     +        * stale bits in PMIIR and PMIMR which gen6_enable_rps will
>     clean up. */
>     +
>     +       spin_lock_irq(&dev_priv->irq_lock);
>     +       dev_priv->rps.pm_iir = 0;
>     +       spin_unlock_irq(&dev_priv->irq_lock);
>     +
>     +       I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
>     +}
>     +
>       static void gen6_disable_rps_interrupts(struct drm_device *dev)
>       {
>              struct drm_i915_private *dev_priv = dev->dev_private;
>     @@ -3116,7 +3135,10 @@ static void gen6_disable_rps(struct
>     drm_device *dev)
>              I915_WRITE(GEN6_RC_CONTROL, 0);
>              I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
>
>     -       gen6_disable_rps_interrupts(dev);
>     +       if (IS_BROADWELL(dev))
>     +               gen8_disable_rps_interrupts(dev);
>     +       else
>     +               gen6_disable_rps_interrupts(dev);
>       }
>
>       static void valleyview_disable_rps(struct drm_device *dev)
>     @@ -3161,6 +3183,19 @@ int intel_enable_rc6(const struct drm_device
>     *dev)
>                      return INTEL_RC6_ENABLE;
>       }
>
>     +static void gen8_enable_rps_interrupts(struct drm_device *dev)
>     +{
>     +       struct drm_i915_private *dev_priv = dev->dev_private;
>     +
>     +       spin_lock_irq(&dev_priv->irq_lock);
>     +       WARN_ON(dev_priv->rps.pm_iir);
>     +       bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
>     +       I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
>     +       spin_unlock_irq(&dev_priv->irq_lock);
>     +
>     +       I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
>     +}

As per the spec, I think we need to unmask bit 31 also, if not i don't 
this we will get PM inetrrupts.

>       static void gen6_enable_rps_interrupts(struct drm_device *dev)
>       {
>              struct drm_i915_private *dev_priv = dev->dev_private;
>     @@ -3263,7 +3298,7 @@ static void gen8_enable_rps(struct drm_device
>     *dev)
>
>              gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00)
>      >> 8);
>
>     -       gen6_enable_rps_interrupts(dev);
>     +       gen8_enable_rps_interrupts(dev);
>
>              gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>       }
>     --
>     1.8.5.3
>
>     _______________________________________________
>     Intel-gfx mailing list
>     Intel-gfx@lists.freedesktop.org <mailto:Intel-gfx@lists.freedesktop.org>
>     http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>

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

* Re: [PATCH 9/9] drm/i915/bdw: Enable RC6
       [not found]   ` <CAOh5HuW-f4xdojasEP3wkSoVH3W1NJNdPACafgnPfVujFe4fjw@mail.gmail.com>
@ 2014-02-07  6:47     ` S, Deepak
  0 siblings, 0 replies; 97+ messages in thread
From: S, Deepak @ 2014-02-07  6:47 UTC (permalink / raw)
  To: benjamin.widawsky, intel-gfx

On Wed, Jan 29, 2014 at 9:55 AM, Ben Widawsky
> <benjamin.widawsky@intel.com <mailto:benjamin.widawsky@intel.com>> wrote:
>
>     It is tested and looking fairly stable now, so turn it on. It wasn't
>     intentionally turned off originally :P
>
>     Signed-off-by: Ben Widawsky <ben@bwidawsk.net <mailto:ben@bwidawsk.net>>
>     ---
>       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 a5c9142..377bd7f 100644
>     --- a/drivers/gpu/drm/i915/intel_pm.c
>     +++ b/drivers/gpu/drm/i915/intel_pm.c
>     @@ -4428,7 +4428,7 @@ void intel_enable_gt_powersave(struct
>     drm_device *dev)
>                      ironlake_enable_drps(dev);
>                      ironlake_enable_rc6(dev);
>                      intel_init_emon(dev);
>     -       } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
>     +       } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(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
>     --
>     1.8.5.3
>
>     _______________________________________________
>     Intel-gfx mailing list
>     Intel-gfx@lists.freedesktop.org <mailto:Intel-gfx@lists.freedesktop.org>
>     http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>

Reviewed-by: Deepak S <deepak.s@intel.com>

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

* Re: [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print
  2014-02-06 13:42   ` Rodrigo Vivi
@ 2014-02-11 16:12     ` Daniel Vetter
  2014-02-14 20:34       ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2014-02-11 16:12 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Intel GFX, Ben Widawsky, Ben Widawsky

On Thu, Feb 06, 2014 at 11:42:39AM -0200, Rodrigo Vivi wrote:
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> 
> On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
> <benjamin.widawsky@intel.com> wrote:
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 944b99c..6acb429 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3215,10 +3215,10 @@ static void gen8_enable_rps(struct drm_device *dev)
> >         /* 3: Enable RC6 */
> >         if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
> >                 rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
> > -       DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
> > +       intel_print_rc6_info(dev, rc6_mask);
> >         I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
> > -                       GEN6_RC_CTL_EI_MODE(1) |
> > -                       rc6_mask);
> > +                                   GEN6_RC_CTL_EI_MODE(1) |
> > +                                   rc6_mask);
> >
> >         /* 4 Program defaults and thresholds for RPS*/
> >         I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
> > --
> > 1.8.5.3
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Merged up to this patch, but after that it gets confusing:
- I have two patches 5/9.
- 6/9 lacks review ...

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

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

* Re: [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print
  2014-02-11 16:12     ` Daniel Vetter
@ 2014-02-14 20:34       ` Ben Widawsky
  2014-02-14 20:41         ` Chris Wilson
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-02-14 20:34 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, Intel GFX, Ben Widawsky

On Tue, Feb 11, 2014 at 05:12:17PM +0100, Daniel Vetter wrote:
> On Thu, Feb 06, 2014 at 11:42:39AM -0200, Rodrigo Vivi wrote:
> > Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> > 
> > On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
> > <benjamin.widawsky@intel.com> wrote:
> > > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > > ---
> > >  drivers/gpu/drm/i915/intel_pm.c | 6 +++---
> > >  1 file changed, 3 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > index 944b99c..6acb429 100644
> > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > @@ -3215,10 +3215,10 @@ static void gen8_enable_rps(struct drm_device *dev)
> > >         /* 3: Enable RC6 */
> > >         if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
> > >                 rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
> > > -       DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
> > > +       intel_print_rc6_info(dev, rc6_mask);
> > >         I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
> > > -                       GEN6_RC_CTL_EI_MODE(1) |
> > > -                       rc6_mask);
> > > +                                   GEN6_RC_CTL_EI_MODE(1) |
> > > +                                   rc6_mask);
> > >
> > >         /* 4 Program defaults and thresholds for RPS*/
> > >         I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
> > > --
> > > 1.8.5.3
> > >
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> Merged up to this patch, but after that it gets confusing:
> - I have two patches 5/9.

5/9 is good to go. Not sure how two got sent out. Rodrigo reviewed the
right one (the patches are the same, but the commit message changed). I
think I accidentally did two git format-patches in my staging area after
doing the rename.

> - 6/9 lacks review ...
> 

6/9 can be skipped for this series, though I think it's a reasonable
patch. Maybe Chris or Jesse has an opinion on 6/9?

> Mailing-list grues ate something?
> -Daniel
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print
  2014-02-14 20:34       ` Ben Widawsky
@ 2014-02-14 20:41         ` Chris Wilson
  2014-02-17 19:41           ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2014-02-14 20:41 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Intel GFX, Ben Widawsky

On Fri, Feb 14, 2014 at 12:34:22PM -0800, Ben Widawsky wrote:
> On Tue, Feb 11, 2014 at 05:12:17PM +0100, Daniel Vetter wrote:
> > - 6/9 lacks review ...
> > 
> 
> 6/9 can be skipped for this series, though I think it's a reasonable
> patch. Maybe Chris or Jesse has an opinion on 6/9?

Yes, programming random values into the hardware is just bonghits. And
then people come along complaining how the idiotic programming guide is
sacrosanct and must be adherred to...

Otoh, changing the value of GEN6_RC_VIDEO_FREQ is worrying as we never
reprogram it nor have I come across any instructions as to what it does.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print
  2014-02-14 20:41         ` Chris Wilson
@ 2014-02-17 19:41           ` Ben Widawsky
  0 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-17 19:41 UTC (permalink / raw)
  To: Chris Wilson, Daniel Vetter, Rodrigo Vivi, Ben Widawsky,
	intel-gfx, Intel GFX, Jesse Barnes

On Fri, Feb 14, 2014 at 08:41:08PM +0000, Chris Wilson wrote:
> On Fri, Feb 14, 2014 at 12:34:22PM -0800, Ben Widawsky wrote:
> > On Tue, Feb 11, 2014 at 05:12:17PM +0100, Daniel Vetter wrote:
> > > - 6/9 lacks review ...
> > > 
> > 
> > 6/9 can be skipped for this series, though I think it's a reasonable
> > patch. Maybe Chris or Jesse has an opinion on 6/9?
> 
> Yes, programming random values into the hardware is just bonghits. And
> then people come along complaining how the idiotic programming guide is
> sacrosanct and must be adherred to...
> 
> Otoh, changing the value of GEN6_RC_VIDEO_FREQ is worrying as we never
> reprogram it nor have I come across any instructions as to what it does.
> -Chris

Can I take a _____by: if I drop GEN6_RC_VIDEO_FREQ?

> 
> -- 
> Chris Wilson, Intel Open Source Technology Centre

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 8/9] drm/i915/bdw: Implement a basic PM interrupt handler
  2014-02-06 14:15   ` Rodrigo Vivi
@ 2014-02-17 20:01     ` Ben Widawsky
  0 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-17 20:01 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Intel GFX, Ben Widawsky

On Thu, Feb 06, 2014 at 12:15:12PM -0200, Rodrigo Vivi wrote:
> On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
> <benjamin.widawsky@intel.com> wrote:
> > Almost all of it is reusable from the existing code. The primary
> > difference is we need to do even less in the interrupt handler, since
> > interrupts are not shared in the same way.
> >
> > The patch is mostly a copy-paste of the existing snb+ code, with updates
> > to the relevant parts requiring changes to the interrupt handling. As
> > such it /should/ be relatively trivial. It's highly likely that I missed
> > some places where I need a gen8 version of the PM interrupts, but it has
> > become invisible to me by now.
> >
> > This patch could probably be split into adding the new functions,
> > followed by actually handling the interrupts. Since the code is
> > currently disabled (and broken) I think the patch stands better by
> > itself.
> >
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > ---
> >  drivers/gpu/drm/i915/i915_irq.c  | 80 ++++++++++++++++++++++++++++++++++++++--
> >  drivers/gpu/drm/i915/i915_reg.h  |  1 +
> >  drivers/gpu/drm/i915/intel_drv.h |  2 +
> >  drivers/gpu/drm/i915/intel_pm.c  | 39 +++++++++++++++++++-
> >  4 files changed, 117 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index 72ade87..ab0c7ac 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -214,6 +214,53 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
> >         return true;
> >  }
> >
> > +/**
> > +  * bdw_update_pm_irq - update GT interrupt 2
> > +  * @dev_priv: driver private
> > +  * @interrupt_mask: mask of interrupt bits to update
> > +  * @enabled_irq_mask: mask of interrupt bits to enable
> > +  *
> > +  * Copied from the snb function, updated with relevant register offsets
> > +  */
> > +static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
> > +                             uint32_t interrupt_mask,
> > +                             uint32_t enabled_irq_mask)
> > +{
> > +       uint32_t new_val;
> > +
> > +       assert_spin_locked(&dev_priv->irq_lock);
> > +
> > +       if (dev_priv->pc8.irqs_disabled) {
> > +               WARN(1, "IRQs disabled\n");
> > +               dev_priv->pc8.regsave.gen6_pmimr &= ~interrupt_mask;
> > +               dev_priv->pc8.regsave.gen6_pmimr |= (~enabled_irq_mask &
> > +                                                    interrupt_mask);
> > +               return;
> > +       }
> > +
> > +       new_val = dev_priv->pm_irq_mask;
> > +       new_val &= ~interrupt_mask;
> > +       new_val |= (~enabled_irq_mask & interrupt_mask);
> > +
> > +       if (new_val != dev_priv->pm_irq_mask) {
> > +               dev_priv->pm_irq_mask = new_val;
> > +               I915_WRITE(GEN8_GT_IMR(2), I915_READ(GEN8_GT_IMR(2)) |
> > +                                          dev_priv->pm_irq_mask);
> > +               POSTING_READ(GEN8_GT_IMR(2));
> > +       }
> > +}
> > +
> > +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
> > +{
> > +       bdw_update_pm_irq(dev_priv, mask, mask);
> > +}
> > +
> > +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
> > +{
> > +       bdw_update_pm_irq(dev_priv, mask, 0);
> > +}
> > +
> > +
> >  static bool cpt_can_enable_serr_int(struct drm_device *dev)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> > @@ -997,11 +1044,15 @@ static void gen6_pm_rps_work(struct work_struct *work)
> >         pm_iir = dev_priv->rps.pm_iir;
> >         dev_priv->rps.pm_iir = 0;
> >         /* Make sure not to corrupt PMIMR state used by ringbuffer code */
> > -       snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> > +       if (IS_BROADWELL(dev_priv->dev))
> > +               bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> > +       else {
> > +               /* Make sure we didn't queue anything we're not going to process. */
> > +               snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> 
> inverted lines since comment sounds to be related to above line.
> 

It's not inverted in it's current state, but it isn't quite clear
either.  I've moved the comment about corruption up to the snb interrupt
write code. It no longer makes sense here at all.

@@ -175,6 +175,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
                return;
        }
 
+       /* Make sure not to corrupt PMIMR state used by ringbuffer code */
        new_val = dev_priv->pm_irq_mask;
        new_val &= ~interrupt_mask;
        new_val |= (~enabled_irq_mask & interrupt_mask);
@@ -1153,17 +1154,16 @@ static void gen6_pm_rps_work(struct work_struct *work)
        spin_lock_irq(&dev_priv->irq_lock);
        pm_iir = dev_priv->rps.pm_iir;
        dev_priv->rps.pm_iir = 0;
-       /* Make sure not to corrupt PMIMR state used by ringbuffer code */
        if (IS_BROADWELL(dev_priv->dev))
                bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
        else {
-               /* Make sure we didn't queue anything we're not going to process. */
                snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+               /* Make sure we didn't queue anything we're not going to
+                * process. */
                WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
        }


> > +               WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
> > +       }
> >         spin_unlock_irq(&dev_priv->irq_lock);
> >
> > -       /* Make sure we didn't queue anything we're not going to process. */
> > -       WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
> >
> >         if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
> >                 return;
> > @@ -1192,6 +1243,19 @@ static void snb_gt_irq_handler(struct drm_device *dev,
> >                 ivybridge_parity_error_irq_handler(dev, gt_iir);
> >  }
> >
> > +static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
> > +{
> > +       if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
> > +               return;
> > +
> > +       spin_lock(&dev_priv->irq_lock);
> > +       dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
> > +       bdw_disable_pm_irq(dev_priv, pm_iir & GEN6_PM_RPS_EVENTS);
> > +       spin_unlock(&dev_priv->irq_lock);
> > +
> > +       queue_work(dev_priv->wq, &dev_priv->rps.work);
> 
> sorry if this is a stupid question, but don't we need the vebox part here?
> 

The reason we do not need a vebox part here is because on gen8 they
split up the PM interrupts and GT interrupts properly. I've only even
kept the separate function to keep with the gen6 style - there isn't
really any risk of complexity like there was pre-gen8.

Even the ring interrupt masks are much easier to manage on gen8, so much
of that code can probably be simplified (I think I left a few comments
or commit msgs stating as much, but I can't recall). At this point, I
just want to get the code running, and RPS working, and then move on.

> > +}
> > +
> >  static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
> >                                        struct drm_i915_private *dev_priv,
> >                                        u32 master_ctl)
> > @@ -1227,6 +1291,16 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
> >                         DRM_ERROR("The master control interrupt lied (GT1)!\n");
> >         }
> >
> > +       if (master_ctl & GEN8_GT_PM_IRQ) {
> > +               tmp = I915_READ(GEN8_GT_IIR(2));
> > +               if (tmp & GEN6_PM_RPS_EVENTS) {
> > +                       ret = IRQ_HANDLED;
> > +                       gen8_rps_irq_handler(dev_priv, tmp);
> > +                       I915_WRITE(GEN8_GT_IIR(1), tmp & GEN6_PM_RPS_EVENTS);
> > +               } else
> > +                       DRM_ERROR("The master control interrupt lied (PM)!\n");
> > +       }
> > +
> >         if (master_ctl & GEN8_GT_VECS_IRQ) {
> >                 tmp = I915_READ(GEN8_GT_IIR(3));
> >                 if (tmp) {
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index d77720e..f9e582e 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -4024,6 +4024,7 @@
> >  #define  GEN8_DE_PIPE_A_IRQ            (1<<16)
> >  #define  GEN8_DE_PIPE_IRQ(pipe)                (1<<(16+pipe))
> >  #define  GEN8_GT_VECS_IRQ              (1<<6)
> > +#define  GEN8_GT_PM_IRQ                        (1<<4)
> >  #define  GEN8_GT_VCS2_IRQ              (1<<3)
> >  #define  GEN8_GT_VCS1_IRQ              (1<<2)
> >  #define  GEN8_GT_BCS_IRQ               (1<<1)
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 44067bc..7b49779 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -608,6 +608,8 @@ void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> >  void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> >  void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> >  void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> > +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> > +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> >  void hsw_pc8_disable_interrupts(struct drm_device *dev);
> >  void hsw_pc8_restore_interrupts(struct drm_device *dev);
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index deaaaf2..a5c9142 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3091,6 +3091,25 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
> >         trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
> >  }
> >
> > +static void gen8_disable_rps_interrupts(struct drm_device *dev)
> > +{
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +
> > +       I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
> > +       I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) &
> > +                                  ~GEN6_PM_RPS_EVENTS);
> > +       /* Complete PM interrupt masking here doesn't race with the rps work
> > +        * item again unmasking PM interrupts because that is using a different
> > +        * register (PMIMR) to mask PM interrupts. The only risk is in leaving
> > +        * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
> > +
> > +       spin_lock_irq(&dev_priv->irq_lock);
> > +       dev_priv->rps.pm_iir = 0;
> > +       spin_unlock_irq(&dev_priv->irq_lock);
> > +
> > +       I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
> > +}
> > +
> >  static void gen6_disable_rps_interrupts(struct drm_device *dev)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> > @@ -3116,7 +3135,10 @@ static void gen6_disable_rps(struct drm_device *dev)
> >         I915_WRITE(GEN6_RC_CONTROL, 0);
> >         I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
> >
> > -       gen6_disable_rps_interrupts(dev);
> > +       if (IS_BROADWELL(dev))
> > +               gen8_disable_rps_interrupts(dev);
> > +       else
> > +               gen6_disable_rps_interrupts(dev);
> >  }
> >
> >  static void valleyview_disable_rps(struct drm_device *dev)
> > @@ -3161,6 +3183,19 @@ int intel_enable_rc6(const struct drm_device *dev)
> >                 return INTEL_RC6_ENABLE;
> >  }
> >
> > +static void gen8_enable_rps_interrupts(struct drm_device *dev)
> > +{
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +
> > +       spin_lock_irq(&dev_priv->irq_lock);
> > +       WARN_ON(dev_priv->rps.pm_iir);
> > +       bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> > +       I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
> > +       spin_unlock_irq(&dev_priv->irq_lock);
> > +
> > +       I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
> > +}
> > +
> >  static void gen6_enable_rps_interrupts(struct drm_device *dev)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> > @@ -3263,7 +3298,7 @@ static void gen8_enable_rps(struct drm_device *dev)
> >
> >         gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
> >
> > -       gen6_enable_rps_interrupts(dev);
> > +       gen8_enable_rps_interrupts(dev);
> >
> >         gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
> >  }
> > --
> > 1.8.5.3
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> with those explained or fixed feel free to use:
> 
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> 

Since I reworked a lot of the code, I was planning to drop your r-b on
some earlier patches too. I'll leave this one unreviewed and you can
tell me how satisfied you are after the repost.

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

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 9/9] drm/i915/bdw: Enable RC6
  2014-02-06 13:54   ` Rodrigo Vivi
@ 2014-02-17 20:04     ` Ben Widawsky
  2014-02-17 20:07       ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-02-17 20:04 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Intel GFX, Ben Widawsky

On Thu, Feb 06, 2014 at 11:54:44AM -0200, Rodrigo Vivi wrote:
> On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
> <benjamin.widawsky@intel.com> wrote:
> > It is tested and looking fairly stable now, so turn it on. It wasn't
> > intentionally turned off originally :P
> >
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > ---
> >  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 a5c9142..377bd7f 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -4428,7 +4428,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
> >                 ironlake_enable_drps(dev);
> >                 ironlake_enable_rc6(dev);
> >                 intel_init_emon(dev);
> > -       } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
> > +       } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
> 
> why not IS_GEN8?
> or why not use gen >= gen6?
> 
> anyway: Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> 

This is my personal preference, though we have some ongoing discussions
in this area. I do not like to explicitly add support for future
platforms except for the most trivial things. I don't think everyone
agrees with me.

Anyway, thanks for the review. I'll be resending the series with a
fairly trivial, though large change.

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

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 9/9] drm/i915/bdw: Enable RC6
  2014-02-17 20:04     ` Ben Widawsky
@ 2014-02-17 20:07       ` Ben Widawsky
  0 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-17 20:07 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Intel GFX, Ben Widawsky

On Mon, Feb 17, 2014 at 12:04:19PM -0800, Ben Widawsky wrote:
> On Thu, Feb 06, 2014 at 11:54:44AM -0200, Rodrigo Vivi wrote:
> > On Wed, Jan 29, 2014 at 2:25 AM, Ben Widawsky
> > <benjamin.widawsky@intel.com> wrote:
> > > It is tested and looking fairly stable now, so turn it on. It wasn't
> > > intentionally turned off originally :P
> > >
> > > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > > ---
> > >  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 a5c9142..377bd7f 100644
> > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > @@ -4428,7 +4428,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
> > >                 ironlake_enable_drps(dev);
> > >                 ironlake_enable_rc6(dev);
> > >                 intel_init_emon(dev);
> > > -       } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
> > > +       } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
> > 
> > why not IS_GEN8?
> > or why not use gen >= gen6?
> > 
> > anyway: Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> > 
> 
> This is my personal preference, though we have some ongoing discussions
> in this area. I do not like to explicitly add support for future
> platforms except for the most trivial things. I don't think everyone
> agrees with me.

s/explicitly/implicitly

> 
> Anyway, thanks for the review. I'll be resending the series with a
> fairly trivial, though large change.
> 
> > 
> > 
> > 
> > -- 
> > Rodrigo Vivi
> > Blog: http://blog.vivi.eng.br
> 
> -- 
> Ben Widawsky, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets
  2014-01-29  4:25 ` [PATCH 1/9] drm/i915: Clarify RC6 enabling Ben Widawsky
  2014-02-06 13:38   ` Rodrigo Vivi
       [not found]   ` <CAOh5HuUmDmAC9Nuu3DWYO2kU+Q5kyHyxSmF4rjADaY1iY6=RaQ@mail.gmail.com>
@ 2014-02-18  3:01   ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 01/11] drm/i915: Reorganize the overclock code Ben Widawsky
                       ` (11 more replies)
  2 siblings, 12 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky

Here is the v2 of the RC6, and RPS enabling for Broadwell. With the last
patch in the series RC6 works without hangs (in limited testing).
Without the last patch, the first batch seems to always hang. I don't
think there any actual fixes over the last version. I changed enough of
the RPS code to not feel comfortable putting Rodrigo's r-b back on.

I had a couple of small tweaks requested by Rodrigo which should be in
there. If they aren't in there, it was a mistake.

Summary:
1-5: All new cleanups new the RPS code.
6: Still in flux default nominal state
7: Pull Jeff's earlier fix around reset into gen8 with a cleanup
8-9: Enable RPS
10-11: Enable RC6

Thanks to Ken for giving this a quick test and allowing me to work from
home :-)


Ben Widawsky (11):
  drm/i915: Reorganize the overclock code
  drm/i915: Fix coding style for RPS
  drm/i915: Rename and comment all the RPS *stuff*
  drm/i915: Remove extraneous MMIO for RPS
  drm/i915: remove rps local variables
  drm/i915/bdw: Set initial rps freq to nominal
  drm/i915/bdw: Extract rp_state_caps logic
  drm/i915/bdw: RPS frequency bits are the same as HSW
  drm/i915/bdw: Implement a basic PM interrupt handler
  drm/i915/bdw: Enable RC6
  drm/i915/bdw: Ensure a context is loaded before RC6

 drivers/gpu/drm/i915/i915_debugfs.c  |  26 ++---
 drivers/gpu/drm/i915/i915_drv.h      |  31 +++--
 drivers/gpu/drm/i915/i915_gem.c      |  12 ++
 drivers/gpu/drm/i915/i915_irq.c      | 108 +++++++++++++++---
 drivers/gpu/drm/i915/i915_reg.h      |   1 +
 drivers/gpu/drm/i915/i915_sysfs.c    |  81 ++++++--------
 drivers/gpu/drm/i915/intel_display.c |   5 +
 drivers/gpu/drm/i915/intel_drv.h     |   2 +
 drivers/gpu/drm/i915/intel_pm.c      | 211 +++++++++++++++++++++--------------
 9 files changed, 308 insertions(+), 169 deletions(-)

-- 
1.8.5.5

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

* [PATCH 01/11] drm/i915: Reorganize the overclock code
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 02/11] drm/i915: Fix coding style for RPS Ben Widawsky
                       ` (10 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

The existing code (which I changed last) was very convoluted. I believe
it was attempting to skip the overclock portion if the previous pcode
write failed. When I last touched the code, I was preserving this
behavior. There is some benefit to doing it that way in that if the
first pcode access fails, the later is likely invalid.

Having a bit more confidence in my understanding of how things work, I
now feel it's better to have clear, readable, code than to try to skip
over this one operation in an unusual case.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index a6b877a..66172b6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3323,7 +3323,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	struct intel_ring_buffer *ring;
 	u32 rp_state_cap, hw_max, hw_min;
 	u32 gt_perf_status;
-	u32 rc6vids, pcu_mbox, rc6_mask = 0;
+	u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
 	u32 gtfifodbg;
 	int rc6_mode;
 	int i, ret;
@@ -3411,17 +3411,15 @@ static void gen6_enable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
 
 	ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0);
-	if (!ret) {
-		pcu_mbox = 0;
-		ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
-		if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
-			DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
-					 (dev_priv->rps.max_delay & 0xff) * 50,
-					 (pcu_mbox & 0xff) * 50);
-			dev_priv->rps.hw_max = pcu_mbox & 0xff;
-		}
-	} else {
+	if (ret)
 		DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
+
+	ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
+	if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
+		DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
+				 (dev_priv->rps.max_delay & 0xff) * 50,
+				 (pcu_mbox & 0xff) * 50);
+		dev_priv->rps.hw_max = pcu_mbox & 0xff;
 	}
 
 	dev_priv->rps.power = HIGH_POWER; /* force a reset */
-- 
1.8.5.5

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

* [PATCH 02/11] drm/i915: Fix coding style for RPS
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
  2014-02-18  3:01     ` [PATCH 01/11] drm/i915: Reorganize the overclock code Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
                       ` (9 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

Introduced:
commit b8a5ff8d7c676a04e0da5ec16bb068dd39459042
Author: Jeff McGee <jeff.mcgee@intel.com>
Date:   Tue Feb 4 11:37:01 2014 -0600

    drm/i915: Update rps interrupt limits

Cc: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_sysfs.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 0c741f4..e9ffefb 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -356,12 +356,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 			valleyview_set_rps(dev, val);
 		else
 			gen6_set_rps(dev, val);
-	}
-	else if (!IS_VALLEYVIEW(dev))
-		/* We still need gen6_set_rps to process the new max_delay
-		   and update the interrupt limits even though frequency
-		   request is unchanged. */
+	} else if (!IS_VALLEYVIEW(dev)) {
+		/* We still need gen6_set_rps to process the new max_delay and
+		 * update the interrupt limits even though frequency request is
+		 * unchanged. */
 		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
@@ -430,12 +430,12 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 			valleyview_set_rps(dev, val);
 		else
 			gen6_set_rps(dev, val);
-	}
-	else if (!IS_VALLEYVIEW(dev))
-		/* We still need gen6_set_rps to process the new min_delay
-		   and update the interrupt limits even though frequency
-		   request is unchanged. */
+	} else if (!IS_VALLEYVIEW(dev)) {
+		/* We still need gen6_set_rps to process the new min_delay and
+		 * update the interrupt limits even though frequency request is
+		 * unchanged. */
 		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-- 
1.8.5.5

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

* [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
  2014-02-18  3:01     ` [PATCH 01/11] drm/i915: Reorganize the overclock code Ben Widawsky
  2014-02-18  3:01     ` [PATCH 02/11] drm/i915: Fix coding style for RPS Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18 19:03       ` [PATCH 03/11] [v2] " Ben Widawsky
  2014-02-22 13:37       ` [PATCH 03/11] " Chris Wilson
  2014-02-18  3:01     ` [PATCH 04/11] drm/i915: Remove extraneous MMIO for RPS Ben Widawsky
                       ` (8 subsequent siblings)
  11 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

The names of the struct members for RPS are stupid. Every time I need to
do anything in this code I have to spend a significant amount of time to
remember what it all means. By renaming the variables (and adding the
comments) I hope to clear up the situation. Indeed doing this make some
upcoming patches more readable.

I've avoided ILK because it's possible that the naming used for Ironlake
matches what is in the docs. I believe the ILK power docs were never
published, and I am too lazy to dig them up.

While there may be mistakes, this patch was mostly done via sed. The
renaming of "hw_max" required a bit of interactivity.

Cc: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  26 ++++----
 drivers/gpu/drm/i915/i915_drv.h     |  31 +++++++---
 drivers/gpu/drm/i915/i915_irq.c     |  24 ++++----
 drivers/gpu/drm/i915/i915_sysfs.c   |  44 +++++++-------
 drivers/gpu/drm/i915/intel_pm.c     | 116 ++++++++++++++++++------------------
 5 files changed, 129 insertions(+), 112 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d90a707..80087d1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1027,7 +1027,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 			   max_freq * GT_FREQUENCY_MULTIPLIER);
 
 		seq_printf(m, "Max overclocked frequency: %dMHz\n",
-			   dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER);
+			   dev_priv->rps.max_freq_overclock * GT_FREQUENCY_MULTIPLIER);
 	} else if (IS_VALLEYVIEW(dev)) {
 		u32 freq_sts, val;
 
@@ -1485,8 +1485,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 
 	seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
-	for (gpu_freq = dev_priv->rps.min_delay;
-	     gpu_freq <= dev_priv->rps.max_delay;
+	for (gpu_freq = dev_priv->rps.min_freq_softlimit;
+	     gpu_freq <= dev_priv->rps.max_freq_softlimit;
 	     gpu_freq++) {
 		ia_freq = gpu_freq;
 		sandybridge_pcode_read(dev_priv,
@@ -3371,9 +3371,9 @@ i915_max_freq_get(void *data, u64 *val)
 		return ret;
 
 	if (IS_VALLEYVIEW(dev))
-		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
+		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit);
 	else
-		*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
+		*val = dev_priv->rps.max_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -3410,16 +3410,16 @@ i915_max_freq_set(void *data, u64 val)
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq_overclock;
 		hw_min = (rp_state_cap >> 16) & 0xff;
 	}
 
-	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
+	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.max_delay = val;
+	dev_priv->rps.max_freq_softlimit = val;
 
 	if (IS_VALLEYVIEW(dev))
 		valleyview_set_rps(dev, val);
@@ -3452,9 +3452,9 @@ i915_min_freq_get(void *data, u64 *val)
 		return ret;
 
 	if (IS_VALLEYVIEW(dev))
-		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
+		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit);
 	else
-		*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
+		*val = dev_priv->rps.min_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -3491,16 +3491,16 @@ i915_min_freq_set(void *data, u64 val)
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq_overclock;
 		hw_min = (rp_state_cap >> 16) & 0xff;
 	}
 
-	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
+	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.min_delay = val;
+	dev_priv->rps.min_freq_softlimit = val;
 
 	if (IS_VALLEYVIEW(dev))
 		valleyview_set_rps(dev, val);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8c64831..e9fdec4 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -967,13 +967,30 @@ struct intel_gen6_power_mgmt {
 	struct work_struct work;
 	u32 pm_iir;
 
-	u8 cur_delay;
-	u8 min_delay;
-	u8 max_delay;
-	u8 rpe_delay;
-	u8 rp1_delay;
-	u8 rp0_delay;
-	u8 hw_max;
+	/* Frequencies are stored in potentially platform dependent multiples.
+	 * In other words, *_freq needs to be multiplied by X to be interesting.
+	 * Soft limits may exist for a variety of reasons, but they can usually
+	 * be overridden through user intervention. Hard limits are actual
+	 * limit.
+	 *
+	 * Soft limits are those which are used for the dynamic reclocking done
+	 * by the driver (raise frequencies under heavy loads, and lower for
+	 * lighter loads). Hard limits are those imposed by the hardware.
+	 *
+	 * A distinction is made for overclocking, which is never enabled by
+	 * default, and is considered to be above the hard limit if it's
+	 * possible at all.
+	 *
+	 * Nominal frequency is a predetermined value to give the best
+	 * performance:power ratio.
+	 */
+	u8 cur_freq; /* Current frequency (cached in SW, may not reflect HW) */
+	u8 min_freq_softlimit; /* Minimum frequency permitted by the driver */
+	u8 max_freq_softlimit; /* Max frequency permitted by the driver */
+	u8 min_freq_hardlimit; /* AKA RP1 Minimum frequency permitted by the GPU */
+	u8 max_freq_hardlimit; /* AKA RP0 Maximum frequency permitted by the GPU */
+	u8 nominal_freq; /* AKA RPn Nominal GPU frequency */
+	u8 max_freq_overclock; /* Max overclocking frequency permitted by the GPU */
 
 	bool rp_up_masked;
 	bool rp_down_masked;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f68aee3..49f2627 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1063,7 +1063,7 @@ void gen6_set_pm_mask(struct drm_i915_private *dev_priv,
 			     u32 pm_iir, int new_delay)
 {
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
-		if (new_delay >= dev_priv->rps.max_delay) {
+		if (new_delay >= dev_priv->rps.max_freq_softlimit) {
 			/* Mask UP THRESHOLD Interrupts */
 			I915_WRITE(GEN6_PMINTRMSK,
 				   I915_READ(GEN6_PMINTRMSK) |
@@ -1078,7 +1078,7 @@ void gen6_set_pm_mask(struct drm_i915_private *dev_priv,
 			dev_priv->rps.rp_down_masked = false;
 		}
 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
-		if (new_delay <= dev_priv->rps.min_delay) {
+		if (new_delay <= dev_priv->rps.min_freq_softlimit) {
 			/* Mask DOWN THRESHOLD Interrupts */
 			I915_WRITE(GEN6_PMINTRMSK,
 				   I915_READ(GEN6_PMINTRMSK) |
@@ -1124,38 +1124,38 @@ static void gen6_pm_rps_work(struct work_struct *work)
 			adj *= 2;
 		else
 			adj = 1;
-		new_delay = dev_priv->rps.cur_delay + adj;
+		new_delay = dev_priv->rps.cur_freq + adj;
 
 		/*
 		 * For better performance, jump directly
 		 * to RPe if we're below it.
 		 */
-		if (new_delay < dev_priv->rps.rpe_delay)
-			new_delay = dev_priv->rps.rpe_delay;
+		if (new_delay < dev_priv->rps.nominal_freq)
+			new_delay = dev_priv->rps.nominal_freq;
 	} else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) {
-		if (dev_priv->rps.cur_delay > dev_priv->rps.rpe_delay)
-			new_delay = dev_priv->rps.rpe_delay;
+		if (dev_priv->rps.cur_freq > dev_priv->rps.nominal_freq)
+			new_delay = dev_priv->rps.nominal_freq;
 		else
-			new_delay = dev_priv->rps.min_delay;
+			new_delay = dev_priv->rps.min_freq_softlimit;
 		adj = 0;
 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
 		if (adj < 0)
 			adj *= 2;
 		else
 			adj = -1;
-		new_delay = dev_priv->rps.cur_delay + adj;
+		new_delay = dev_priv->rps.cur_freq + adj;
 	} else { /* unknown event */
-		new_delay = dev_priv->rps.cur_delay;
+		new_delay = dev_priv->rps.cur_freq;
 	}
 
 	/* sysfs frequency interfaces may have snuck in while servicing the
 	 * interrupt
 	 */
 	new_delay = clamp_t(int, new_delay,
-			    dev_priv->rps.min_delay, dev_priv->rps.max_delay);
+			    dev_priv->rps.min_freq_softlimit, dev_priv->rps.max_freq_softlimit);
 
 	gen6_set_pm_mask(dev_priv, pm_iir, new_delay);
-	dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
+	dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_freq;
 
 	if (IS_VALLEYVIEW(dev_priv->dev))
 		valleyview_set_rps(dev_priv->dev, new_delay);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e9ffefb..86999aa 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -269,7 +269,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 		freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
 		ret = vlv_gpu_freq(dev_priv, (freq >> 8) & 0xff);
 	} else {
-		ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.cur_freq * GT_FREQUENCY_MULTIPLIER;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
@@ -284,7 +284,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-			vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay));
+			vlv_gpu_freq(dev_priv, dev_priv->rps.nominal_freq));
 }
 
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -298,9 +298,9 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (IS_VALLEYVIEW(dev_priv->dev))
-		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
+		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit);
 	else
-		ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.max_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -334,13 +334,13 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		val /= GT_FREQUENCY_MULTIPLIER;
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq_overclock;
 		non_oc_max = (rp_state_cap & 0xff);
 		hw_min = ((rp_state_cap & 0xff0000) >> 16);
 	}
 
 	if (val < hw_min || val > hw_max ||
-	    val < dev_priv->rps.min_delay) {
+	    val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
@@ -349,18 +349,18 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		DRM_DEBUG("User requested overclocking to %d\n",
 			  val * GT_FREQUENCY_MULTIPLIER);
 
-	dev_priv->rps.max_delay = val;
+	dev_priv->rps.max_freq_softlimit = val;
 
-	if (dev_priv->rps.cur_delay > val) {
+	if (dev_priv->rps.cur_freq > val) {
 		if (IS_VALLEYVIEW(dev))
 			valleyview_set_rps(dev, val);
 		else
 			gen6_set_rps(dev, val);
 	} else if (!IS_VALLEYVIEW(dev)) {
-		/* We still need gen6_set_rps to process the new max_delay and
-		 * update the interrupt limits even though frequency request is
-		 * unchanged. */
-		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+		/* We still need gen6_set_rps to process the new
+		 * max_freq_softlimit and update the interrupt limits even
+		 * though frequency request is unchanged. */
+		gen6_set_rps(dev, dev_priv->rps.cur_freq);
 	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -379,9 +379,9 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (IS_VALLEYVIEW(dev_priv->dev))
-		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
+		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit);
 	else
-		ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.min_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -414,27 +414,27 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 		val /= GT_FREQUENCY_MULTIPLIER;
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq_overclock;
 		hw_min = ((rp_state_cap & 0xff0000) >> 16);
 	}
 
-	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
+	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.min_delay = val;
+	dev_priv->rps.min_freq_softlimit = val;
 
-	if (dev_priv->rps.cur_delay < val) {
+	if (dev_priv->rps.cur_freq < val) {
 		if (IS_VALLEYVIEW(dev))
 			valleyview_set_rps(dev, val);
 		else
 			gen6_set_rps(dev, val);
 	} else if (!IS_VALLEYVIEW(dev)) {
-		/* We still need gen6_set_rps to process the new min_delay and
-		 * update the interrupt limits even though frequency request is
-		 * unchanged. */
-		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+		/* We still need gen6_set_rps to process the new
+		 * min_freq_softlimit and update the interrupt limits even
+		 * though frequency request is unchanged. */
+		gen6_set_rps(dev, dev_priv->rps.cur_freq);
 	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 66172b6..341c154 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2904,9 +2904,9 @@ static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 val)
 	 * the hw runs at the minimal clock before selecting the desired
 	 * frequency, if the down threshold expires in that window we will not
 	 * receive a down interrupt. */
-	limits = dev_priv->rps.max_delay << 24;
-	if (val <= dev_priv->rps.min_delay)
-		limits |= dev_priv->rps.min_delay << 16;
+	limits = dev_priv->rps.max_freq_softlimit << 24;
+	if (val <= dev_priv->rps.min_freq_softlimit)
+		limits |= dev_priv->rps.min_freq_softlimit << 16;
 
 	return limits;
 }
@@ -2918,26 +2918,26 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 	new_power = dev_priv->rps.power;
 	switch (dev_priv->rps.power) {
 	case LOW_POWER:
-		if (val > dev_priv->rps.rpe_delay + 1 && val > dev_priv->rps.cur_delay)
+		if (val > dev_priv->rps.nominal_freq + 1 && val > dev_priv->rps.cur_freq)
 			new_power = BETWEEN;
 		break;
 
 	case BETWEEN:
-		if (val <= dev_priv->rps.rpe_delay && val < dev_priv->rps.cur_delay)
+		if (val <= dev_priv->rps.nominal_freq && val < dev_priv->rps.cur_freq)
 			new_power = LOW_POWER;
-		else if (val >= dev_priv->rps.rp0_delay && val > dev_priv->rps.cur_delay)
+		else if (val >= dev_priv->rps.max_freq_hardlimit && val > dev_priv->rps.cur_freq)
 			new_power = HIGH_POWER;
 		break;
 
 	case HIGH_POWER:
-		if (val < (dev_priv->rps.rp1_delay + dev_priv->rps.rp0_delay) >> 1 && val < dev_priv->rps.cur_delay)
+		if (val < (dev_priv->rps.min_freq_hardlimit + dev_priv->rps.max_freq_hardlimit) >> 1 && val < dev_priv->rps.cur_freq)
 			new_power = BETWEEN;
 		break;
 	}
 	/* Max/min bins are special */
-	if (val == dev_priv->rps.min_delay)
+	if (val == dev_priv->rps.min_freq_softlimit)
 		new_power = LOW_POWER;
-	if (val == dev_priv->rps.max_delay)
+	if (val == dev_priv->rps.max_freq_softlimit)
 		new_power = HIGH_POWER;
 	if (new_power == dev_priv->rps.power)
 		return;
@@ -3004,17 +3004,17 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 }
 
 /* gen6_set_rps is called to update the frequency request, but should also be
- * called when the range (min_delay and max_delay) is modified so that we can
+ * called when the range (min_freq_softlimit and max_freq_softlimit) is modified so that we can
  * update the GEN6_RP_INTERRUPT_LIMITS register accordingly. */
 void gen6_set_rps(struct drm_device *dev, u8 val)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-	WARN_ON(val > dev_priv->rps.max_delay);
-	WARN_ON(val < dev_priv->rps.min_delay);
+	WARN_ON(val > dev_priv->rps.max_freq_softlimit);
+	WARN_ON(val < dev_priv->rps.min_freq_softlimit);
 
-	if (val == dev_priv->rps.cur_delay) {
+	if (val == dev_priv->rps.cur_freq) {
 		/* min/max delay may still have been modified so be sure to
 		 * write the limits value */
 		I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
@@ -3042,7 +3042,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 
 	POSTING_READ(GEN6_RPNSWREQ);
 
-	dev_priv->rps.cur_delay = val;
+	dev_priv->rps.cur_freq = val;
 
 	trace_intel_gpu_freq_change(val * 50);
 }
@@ -3062,7 +3062,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 	 * When we are idle.  Drop to min voltage state.
 	 */
 
-	if (dev_priv->rps.cur_delay <= dev_priv->rps.min_delay)
+	if (dev_priv->rps.cur_freq <= dev_priv->rps.min_freq_softlimit)
 		return;
 
 	/* Mask turbo interrupt so that they will not come in between */
@@ -3079,10 +3079,10 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 		return;
 	}
 
-	dev_priv->rps.cur_delay = dev_priv->rps.min_delay;
+	dev_priv->rps.cur_freq = dev_priv->rps.min_freq_softlimit;
 
 	vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ,
-					dev_priv->rps.min_delay);
+					dev_priv->rps.min_freq_softlimit);
 
 	if (wait_for(((vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS))
 				& GENFREQSTATUS) == 0, 5))
@@ -3096,7 +3096,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 	/* Unmask Up interrupts */
 	dev_priv->rps.rp_up_masked = true;
 	gen6_set_pm_mask(dev_priv, GEN6_PM_RP_DOWN_THRESHOLD,
-						dev_priv->rps.min_delay);
+						dev_priv->rps.min_freq_softlimit);
 }
 
 void gen6_rps_idle(struct drm_i915_private *dev_priv)
@@ -3108,7 +3108,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
 		if (IS_VALLEYVIEW(dev))
 			vlv_set_rps_idle(dev_priv);
 		else
-			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
+			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
 		dev_priv->rps.last_adj = 0;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -3121,9 +3121,9 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv)
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (dev_priv->rps.enabled) {
 		if (IS_VALLEYVIEW(dev))
-			valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
+			valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit);
 		else
-			gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
+			gen6_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit);
 		dev_priv->rps.last_adj = 0;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -3134,20 +3134,20 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-	WARN_ON(val > dev_priv->rps.max_delay);
-	WARN_ON(val < dev_priv->rps.min_delay);
+	WARN_ON(val > dev_priv->rps.max_freq_softlimit);
+	WARN_ON(val < dev_priv->rps.min_freq_softlimit);
 
 	DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
-			 dev_priv->rps.cur_delay,
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
+			 dev_priv->rps.cur_freq,
 			 vlv_gpu_freq(dev_priv, val), val);
 
-	if (val == dev_priv->rps.cur_delay)
+	if (val == dev_priv->rps.cur_freq)
 		return;
 
 	vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val);
 
-	dev_priv->rps.cur_delay = val;
+	dev_priv->rps.cur_freq = val;
 
 	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
@@ -3289,8 +3289,8 @@ static void gen8_enable_rps(struct drm_device *dev)
 
 	/* Docs recommend 900MHz, and 300 MHz respectively */
 	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
-		   dev_priv->rps.max_delay << 24 |
-		   dev_priv->rps.min_delay << 16);
+		   dev_priv->rps.max_freq_softlimit << 24 |
+		   dev_priv->rps.min_freq_softlimit << 16);
 
 	I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */
 	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/
@@ -3350,19 +3350,19 @@ static void gen6_enable_rps(struct drm_device *dev)
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
 	/* In units of 50MHz */
-	dev_priv->rps.hw_max = hw_max = rp_state_cap & 0xff;
+	dev_priv->rps.max_freq_overclock = hw_max = rp_state_cap & 0xff;
 	hw_min = (rp_state_cap >> 16) & 0xff;
-	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
-	dev_priv->rps.cur_delay = 0;
+	dev_priv->rps.min_freq_hardlimit = (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.max_freq_hardlimit = (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.nominal_freq = dev_priv->rps.min_freq_hardlimit;
+	dev_priv->rps.cur_freq = 0;
 
 	/* Preserve min/max settings in case of re-init */
-	if (dev_priv->rps.max_delay == 0)
-		dev_priv->rps.max_delay = hw_max;
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = hw_max;
 
-	if (dev_priv->rps.min_delay == 0)
-		dev_priv->rps.min_delay = hw_min;
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = hw_min;
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -3417,13 +3417,13 @@ static void gen6_enable_rps(struct drm_device *dev)
 	ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
 	if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
 		DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
-				 (dev_priv->rps.max_delay & 0xff) * 50,
+				 (dev_priv->rps.max_freq_softlimit & 0xff) * 50,
 				 (pcu_mbox & 0xff) * 50);
-		dev_priv->rps.hw_max = pcu_mbox & 0xff;
+		dev_priv->rps.max_freq_overclock = pcu_mbox & 0xff;
 	}
 
 	dev_priv->rps.power = HIGH_POWER; /* force a reset */
-	gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
+	gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
 
 	gen6_enable_rps_interrupts(dev);
 
@@ -3479,9 +3479,9 @@ void gen6_update_ring_freq(struct drm_device *dev)
 	 * to use for memory access.  We do this by specifying the IA frequency
 	 * the PCU should use as a reference to determine the ring frequency.
 	 */
-	for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay;
+	for (gpu_freq = dev_priv->rps.max_freq_softlimit; gpu_freq >= dev_priv->rps.min_freq_softlimit;
 	     gpu_freq--) {
-		int diff = dev_priv->rps.max_delay - gpu_freq;
+		int diff = dev_priv->rps.max_freq_softlimit - gpu_freq;
 		unsigned int ia_freq = 0, ring_freq = 0;
 
 		if (INTEL_INFO(dev)->gen >= 8) {
@@ -3647,20 +3647,20 @@ static void valleyview_enable_rps(struct drm_device *dev)
 	DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
 	DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
 
-	dev_priv->rps.cur_delay = (val >> 8) & 0xff;
+	dev_priv->rps.cur_freq = (val >> 8) & 0xff;
 	DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
-			 dev_priv->rps.cur_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
+			 dev_priv->rps.cur_freq);
 
-	dev_priv->rps.hw_max = hw_max = valleyview_rps_max_freq(dev_priv);
+	dev_priv->rps.max_freq_overclock = hw_max = valleyview_rps_max_freq(dev_priv);
 	DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
 			 vlv_gpu_freq(dev_priv, hw_max),
 			 hw_max);
 
-	dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv);
+	dev_priv->rps.nominal_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.rpe_delay),
-			 dev_priv->rps.rpe_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.nominal_freq),
+			 dev_priv->rps.nominal_freq);
 
 	hw_min = valleyview_rps_min_freq(dev_priv);
 	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
@@ -3668,17 +3668,17 @@ static void valleyview_enable_rps(struct drm_device *dev)
 			 hw_min);
 
 	/* Preserve min/max settings in case of re-init */
-	if (dev_priv->rps.max_delay == 0)
-		dev_priv->rps.max_delay = hw_max;
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = hw_max;
 
-	if (dev_priv->rps.min_delay == 0)
-		dev_priv->rps.min_delay = hw_min;
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = hw_min;
 
 	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
-			 dev_priv->rps.rpe_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.nominal_freq),
+			 dev_priv->rps.nominal_freq);
 
-	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
+	valleyview_set_rps(dev_priv->dev, dev_priv->rps.nominal_freq);
 
 	dev_priv->rps.rp_up_masked = false;
 	dev_priv->rps.rp_down_masked = false;
@@ -4119,7 +4119,7 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
 
 	assert_spin_locked(&mchdev_lock);
 
-	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_delay * 4));
+	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_freq * 4));
 	pxvid = (pxvid >> 24) & 0x7f;
 	ext_v = pvid_to_extvid(dev_priv, pxvid);
 
-- 
1.8.5.5

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

* [PATCH 04/11] drm/i915: Remove extraneous MMIO for RPS
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (2 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 05/11] drm/i915: remove rps local variables Ben Widawsky
                       ` (7 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

The values created at initialization must always exist to use the
interface. Reading them again is confusing, and pointless.

More cleanups are coming in the next patch. Since I am not 100% certain,
moreso on BYT, (though I am extremely close to that) that there is no
need to leave the MMIO here, I wanted to make it a separate patch for
the bisectable 'just-in-case'

Cc: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_sysfs.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 86999aa..27cf344 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -313,7 +313,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	struct drm_minor *minor = dev_to_drm_minor(kdev);
 	struct drm_device *dev = minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 val, rp_state_cap, hw_max, hw_min, non_oc_max;
+	u32 val, hw_max, hw_min, non_oc_max;
 	ssize_t ret;
 
 	ret = kstrtou32(buf, 0, &val);
@@ -327,16 +327,15 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	if (IS_VALLEYVIEW(dev_priv->dev)) {
 		val = vlv_freq_opcode(dev_priv, val);
 
-		hw_max = valleyview_rps_max_freq(dev_priv);
-		hw_min = valleyview_rps_min_freq(dev_priv);
+		hw_max = dev_priv->rps.max_freq_hardlimit;
+		hw_min = dev_priv->rps.min_freq_hardlimit;
 		non_oc_max = hw_max;
 	} else {
 		val /= GT_FREQUENCY_MULTIPLIER;
 
-		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 		hw_max = dev_priv->rps.max_freq_overclock;
-		non_oc_max = (rp_state_cap & 0xff);
-		hw_min = ((rp_state_cap & 0xff0000) >> 16);
+		non_oc_max = dev_priv->rps.max_freq_hardlimit;
+		hw_min = dev_priv->rps.min_freq_hardlimit;
 	}
 
 	if (val < hw_min || val > hw_max ||
@@ -394,7 +393,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	struct drm_minor *minor = dev_to_drm_minor(kdev);
 	struct drm_device *dev = minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 val, rp_state_cap, hw_max, hw_min;
+	u32 val, hw_max, hw_min;
 	ssize_t ret;
 
 	ret = kstrtou32(buf, 0, &val);
@@ -408,14 +407,13 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	if (IS_VALLEYVIEW(dev)) {
 		val = vlv_freq_opcode(dev_priv, val);
 
-		hw_max = valleyview_rps_max_freq(dev_priv);
-		hw_min = valleyview_rps_min_freq(dev_priv);
+		hw_max = dev_priv->rps.max_freq_hardlimit;
+		hw_min = dev_priv->rps.min_freq_hardlimit;
 	} else {
 		val /= GT_FREQUENCY_MULTIPLIER;
 
-		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 		hw_max = dev_priv->rps.max_freq_overclock;
-		hw_min = ((rp_state_cap & 0xff0000) >> 16);
+		hw_min = dev_priv->rps.min_freq_hardlimit;
 	}
 
 	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
-- 
1.8.5.5

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

* [PATCH 05/11] drm/i915: remove rps local variables
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (3 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 04/11] drm/i915: Remove extraneous MMIO for RPS Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 06/11] drm/i915/bdw: Set initial rps freq to nominal Ben Widawsky
                       ` (6 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

With the renamed RPS struct members, it's easier to skip the local
variables which no longer clarify anything, and if anything just make
the code harder to read.

The real motivation for this patch is actually the next patch, which
attempts to consolidate some of the functionality.

Cc: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_sysfs.c | 37 ++++++++++++-------------------------
 drivers/gpu/drm/i915/intel_pm.c   | 29 +++++++++++++++--------------
 2 files changed, 27 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 27cf344..6f83cca 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -313,7 +313,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	struct drm_minor *minor = dev_to_drm_minor(kdev);
 	struct drm_device *dev = minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 val, hw_max, hw_min, non_oc_max;
+	u32 val;
 	ssize_t ret;
 
 	ret = kstrtou32(buf, 0, &val);
@@ -324,27 +324,19 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev_priv->dev)) {
+	if (IS_VALLEYVIEW(dev_priv->dev))
 		val = vlv_freq_opcode(dev_priv, val);
-
-		hw_max = dev_priv->rps.max_freq_hardlimit;
-		hw_min = dev_priv->rps.min_freq_hardlimit;
-		non_oc_max = hw_max;
-	} else {
+	else
 		val /= GT_FREQUENCY_MULTIPLIER;
 
-		hw_max = dev_priv->rps.max_freq_overclock;
-		non_oc_max = dev_priv->rps.max_freq_hardlimit;
-		hw_min = dev_priv->rps.min_freq_hardlimit;
-	}
-
-	if (val < hw_min || val > hw_max ||
+	if (val < dev_priv->rps.min_freq_hardlimit ||
+	    val > dev_priv->rps.max_freq_overclock ||
 	    val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	if (val > non_oc_max)
+	if (val > dev_priv->rps.max_freq_hardlimit)
 		DRM_DEBUG("User requested overclocking to %d\n",
 			  val * GT_FREQUENCY_MULTIPLIER);
 
@@ -393,7 +385,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	struct drm_minor *minor = dev_to_drm_minor(kdev);
 	struct drm_device *dev = minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 val, hw_max, hw_min;
+	u32 val;
 	ssize_t ret;
 
 	ret = kstrtou32(buf, 0, &val);
@@ -404,19 +396,14 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev))
 		val = vlv_freq_opcode(dev_priv, val);
-
-		hw_max = dev_priv->rps.max_freq_hardlimit;
-		hw_min = dev_priv->rps.min_freq_hardlimit;
-	} else {
+	else
 		val /= GT_FREQUENCY_MULTIPLIER;
 
-		hw_max = dev_priv->rps.max_freq_overclock;
-		hw_min = dev_priv->rps.min_freq_hardlimit;
-	}
-
-	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
+	if (val < dev_priv->rps.min_freq_hardlimit ||
+	    val > dev_priv->rps.max_freq_overclock ||
+	    val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 341c154..e63515a 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3321,7 +3321,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	u32 rp_state_cap, hw_max, hw_min;
+	u32 rp_state_cap;
 	u32 gt_perf_status;
 	u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
 	u32 gtfifodbg;
@@ -3350,19 +3350,19 @@ static void gen6_enable_rps(struct drm_device *dev)
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
 	/* In units of 50MHz */
-	dev_priv->rps.max_freq_overclock = hw_max = rp_state_cap & 0xff;
-	hw_min = (rp_state_cap >> 16) & 0xff;
+	dev_priv->rps.nominal_freq	 = (rp_state_cap >> 16) & 0xff;
 	dev_priv->rps.min_freq_hardlimit = (rp_state_cap >>  8) & 0xff;
 	dev_priv->rps.max_freq_hardlimit = (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.max_freq_overclock = dev_priv->rps.max_freq_hardlimit;
 	dev_priv->rps.nominal_freq = dev_priv->rps.min_freq_hardlimit;
 	dev_priv->rps.cur_freq = 0;
 
 	/* Preserve min/max settings in case of re-init */
 	if (dev_priv->rps.max_freq_softlimit == 0)
-		dev_priv->rps.max_freq_softlimit = hw_max;
+		dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq_hardlimit;
 
 	if (dev_priv->rps.min_freq_softlimit == 0)
-		dev_priv->rps.min_freq_softlimit = hw_min;
+		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq_hardlimit;
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -3590,7 +3590,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	u32 gtfifodbg, val, hw_max, hw_min, rc6_mode = 0;
+	u32 gtfifodbg, val, rc6_mode = 0;
 	int i;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -3652,27 +3652,28 @@ 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_overclock = hw_max = valleyview_rps_max_freq(dev_priv);
+	dev_priv->rps.max_freq_hardlimit = valleyview_rps_max_freq(dev_priv);
+	dev_priv->rps.max_freq_overclock = dev_priv->rps.max_freq_hardlimit;
 	DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, hw_max),
-			 hw_max);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq_hardlimit),
+			 dev_priv->rps.max_freq_hardlimit);
 
 	dev_priv->rps.nominal_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.nominal_freq),
 			 dev_priv->rps.nominal_freq);
 
-	hw_min = valleyview_rps_min_freq(dev_priv);
+	dev_priv->rps.min_freq_hardlimit = valleyview_rps_min_freq(dev_priv);
 	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, hw_min),
-			 hw_min);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq_hardlimit),
+			 dev_priv->rps.min_freq_hardlimit);
 
 	/* Preserve min/max settings in case of re-init */
 	if (dev_priv->rps.max_freq_softlimit == 0)
-		dev_priv->rps.max_freq_softlimit = hw_max;
+		dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq_hardlimit;
 
 	if (dev_priv->rps.min_freq_softlimit == 0)
-		dev_priv->rps.min_freq_softlimit = hw_min;
+		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq_hardlimit;
 
 	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
 			 vlv_gpu_freq(dev_priv, dev_priv->rps.nominal_freq),
-- 
1.8.5.5

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

* [PATCH 06/11] drm/i915/bdw: Set initial rps freq to nominal
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (4 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 05/11] drm/i915: remove rps local variables Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 07/11] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
                       ` (5 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

Programming it outside of the rp0-rp1 range is considered a programming
error. Since we do not know that the previous value would actually be in
the range, program something we've read from the hardware, and therefore
know will work.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e63515a..4fe9a94 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3282,8 +3282,10 @@ static void gen8_enable_rps(struct drm_device *dev)
 				    rc6_mask);
 
 	/* 4 Program defaults and thresholds for RPS*/
-	I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
-	I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(12)); /* Request 600 MHz */
+	I915_WRITE(GEN6_RPNSWREQ,
+		   HSW_FREQUENCY(dev_priv->rps.nominal_freq));
+	I915_WRITE(GEN6_RC_VIDEO_FREQ,
+		   HSW_FREQUENCY(dev_priv->rps.nominal_freq));
 	/* NB: Docs say 1s, and 1000000 - which aren't equivalent */
 	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */
 
-- 
1.8.5.5

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

* [PATCH 07/11] drm/i915/bdw: Extract rp_state_caps logic
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (5 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 06/11] drm/i915/bdw: Set initial rps freq to nominal Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 08/11] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
                       ` (4 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

We have a need for duplicated parsing of the RP_STATE_CAPS register (and
the setting of the associated fields). To reuse some code, we can
extract the function into a simple helper.

This patch also addresses the fact that we missed doing this for gen8,
something we should have done anyway.

This could be two patches, one to extract, and one to add gen8, but it's
trivial enough that I think one is fine. I will accept a request to
split it. Please notice the fix addressed by v2 below.

Valleyview is left untouched because it is different.

v2: Logically rebased on top of
commit dd0a1aa19bd3d7203e58157b84cea78bbac605ac
Author: Jeff McGee <jeff.mcgee@intel.com>
Date:   Tue Feb 4 11:32:31 2014 -0600

    drm/i915: Restore rps/rc6 on reset

Note with the above change the fix for gen8 is also handled (which was
not the case in Jeff's original patch).

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 4fe9a94..ac8419d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3245,6 +3245,25 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev)
 	I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs);
 }
 
+static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_cap)
+{
+
+	/* In units of 50MHz */
+	dev_priv->rps.nominal_freq	 = (rp_state_cap >> 16) & 0xff;
+	dev_priv->rps.min_freq_hardlimit = (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.max_freq_hardlimit = (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.max_freq_overclock = dev_priv->rps.max_freq_hardlimit;
+	dev_priv->rps.nominal_freq = dev_priv->rps.min_freq_hardlimit;
+	dev_priv->rps.cur_freq = 0;
+
+	/* 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_hardlimit;
+
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq_hardlimit;
+}
+
 static void gen8_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3263,6 +3282,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* 2b: Program RC6 thresholds.*/
 	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
@@ -3351,20 +3371,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
-	/* In units of 50MHz */
-	dev_priv->rps.nominal_freq	 = (rp_state_cap >> 16) & 0xff;
-	dev_priv->rps.min_freq_hardlimit = (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.max_freq_hardlimit = (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.max_freq_overclock = dev_priv->rps.max_freq_hardlimit;
-	dev_priv->rps.nominal_freq = dev_priv->rps.min_freq_hardlimit;
-	dev_priv->rps.cur_freq = 0;
-
-	/* 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_hardlimit;
-
-	if (dev_priv->rps.min_freq_softlimit == 0)
-		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq_hardlimit;
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
-- 
1.8.5.5

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

* [PATCH 08/11] drm/i915/bdw: RPS frequency bits are the same as HSW
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (6 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 07/11] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 09/11] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
                       ` (3 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 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 ac8419d..6259e47 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3025,7 +3025,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 
 	gen6_set_rps_thresholds(dev_priv, val);
 
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		I915_WRITE(GEN6_RPNSWREQ,
 			   HSW_FREQUENCY(val));
 	else
-- 
1.8.5.5

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

* [PATCH 09/11] drm/i915/bdw: Implement a basic PM interrupt handler
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (7 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 08/11] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 10/11] drm/i915/bdw: Enable RC6 Ben Widawsky
                       ` (2 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

Almost all of it is reusable from the existing code. The primary
difference is we need to do even less in the interrupt handler, since
interrupts are not shared in the same way.

The patch is mostly a copy-paste of the existing snb+ code, with updates
to the relevant parts requiring changes to the interrupt handling. As
such it /should/ be relatively trivial. It's highly likely that I missed
some places where I need a gen8 version of the PM interrupts, but it has
become invisible to me by now.

This patch could probably be split into adding the new functions,
followed by actually handling the interrupts. Since the code is
currently disabled (and broken) I think the patch stands better by
itself.

v2: Move the commit about not touching the ringbuffer interrupt to the
snb_* function where it belongs (Rodrigo)

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_irq.c  | 84 +++++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_drv.h |  2 +
 drivers/gpu/drm/i915/intel_pm.c  | 39 ++++++++++++++++++-
 4 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 49f2627..9669dce 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -175,6 +175,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
 		return;
 	}
 
+	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
 	new_val = dev_priv->pm_irq_mask;
 	new_val &= ~interrupt_mask;
 	new_val |= (~enabled_irq_mask & interrupt_mask);
@@ -214,6 +215,53 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
 	return true;
 }
 
+/**
+  * bdw_update_pm_irq - update GT interrupt 2
+  * @dev_priv: driver private
+  * @interrupt_mask: mask of interrupt bits to update
+  * @enabled_irq_mask: mask of interrupt bits to enable
+  *
+  * Copied from the snb function, updated with relevant register offsets
+  */
+static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
+			      uint32_t interrupt_mask,
+			      uint32_t enabled_irq_mask)
+{
+	uint32_t new_val;
+
+	assert_spin_locked(&dev_priv->irq_lock);
+
+	if (dev_priv->pc8.irqs_disabled) {
+		WARN(1, "IRQs disabled\n");
+		dev_priv->pc8.regsave.gen6_pmimr &= ~interrupt_mask;
+		dev_priv->pc8.regsave.gen6_pmimr |= (~enabled_irq_mask &
+						     interrupt_mask);
+		return;
+	}
+
+	new_val = dev_priv->pm_irq_mask;
+	new_val &= ~interrupt_mask;
+	new_val |= (~enabled_irq_mask & interrupt_mask);
+
+	if (new_val != dev_priv->pm_irq_mask) {
+		dev_priv->pm_irq_mask = new_val;
+		I915_WRITE(GEN8_GT_IMR(2), I915_READ(GEN8_GT_IMR(2)) |
+					   dev_priv->pm_irq_mask);
+		POSTING_READ(GEN8_GT_IMR(2));
+	}
+}
+
+void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+{
+	bdw_update_pm_irq(dev_priv, mask, mask);
+}
+
+void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+{
+	bdw_update_pm_irq(dev_priv, mask, 0);
+}
+
+
 static bool cpt_can_enable_serr_int(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1106,13 +1154,16 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	spin_lock_irq(&dev_priv->irq_lock);
 	pm_iir = dev_priv->rps.pm_iir;
 	dev_priv->rps.pm_iir = 0;
-	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
-	snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	if (IS_BROADWELL(dev_priv->dev))
+		bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	else {
+		snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+		/* Make sure we didn't queue anything we're not going to
+		 * process. */
+		WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
+	}
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	/* Make sure we didn't queue anything we're not going to process. */
-	WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
-
 	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
 		return;
 
@@ -1304,6 +1355,19 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 		ivybridge_parity_error_irq_handler(dev, gt_iir);
 }
 
+static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
+{
+	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
+		return;
+
+	spin_lock(&dev_priv->irq_lock);
+	dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
+	bdw_disable_pm_irq(dev_priv, pm_iir & GEN6_PM_RPS_EVENTS);
+	spin_unlock(&dev_priv->irq_lock);
+
+	queue_work(dev_priv->wq, &dev_priv->rps.work);
+}
+
 static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
 				       struct drm_i915_private *dev_priv,
 				       u32 master_ctl)
@@ -1339,6 +1403,16 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
 			DRM_ERROR("The master control interrupt lied (GT1)!\n");
 	}
 
+	if (master_ctl & GEN8_GT_PM_IRQ) {
+		tmp = I915_READ(GEN8_GT_IIR(2));
+		if (tmp & GEN6_PM_RPS_EVENTS) {
+			ret = IRQ_HANDLED;
+			gen8_rps_irq_handler(dev_priv, tmp);
+			I915_WRITE(GEN8_GT_IIR(1), tmp & GEN6_PM_RPS_EVENTS);
+		} else
+			DRM_ERROR("The master control interrupt lied (PM)!\n");
+	}
+
 	if (master_ctl & GEN8_GT_VECS_IRQ) {
 		tmp = I915_READ(GEN8_GT_IIR(3));
 		if (tmp) {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2f564ce..6ca6a95 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4055,6 +4055,7 @@
 #define  GEN8_DE_PIPE_A_IRQ		(1<<16)
 #define  GEN8_DE_PIPE_IRQ(pipe)		(1<<(16+pipe))
 #define  GEN8_GT_VECS_IRQ		(1<<6)
+#define  GEN8_GT_PM_IRQ			(1<<4)
 #define  GEN8_GT_VCS2_IRQ		(1<<3)
 #define  GEN8_GT_VCS1_IRQ		(1<<2)
 #define  GEN8_GT_BCS_IRQ		(1<<1)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a4ffc02..c2fa7b8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -616,6 +616,8 @@ void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void hsw_pc8_disable_interrupts(struct drm_device *dev);
 void hsw_pc8_restore_interrupts(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6259e47..c2980ff 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3152,6 +3152,25 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
 
+static void gen8_disable_rps_interrupts(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+	I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) &
+				   ~GEN6_PM_RPS_EVENTS);
+	/* Complete PM interrupt masking here doesn't race with the rps work
+	 * item again unmasking PM interrupts because that is using a different
+	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
+
+	spin_lock_irq(&dev_priv->irq_lock);
+	dev_priv->rps.pm_iir = 0;
+	spin_unlock_irq(&dev_priv->irq_lock);
+
+	I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
+}
+
 static void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3177,7 +3196,10 @@ static void gen6_disable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
 
-	gen6_disable_rps_interrupts(dev);
+	if (IS_BROADWELL(dev))
+		gen8_disable_rps_interrupts(dev);
+	else
+		gen6_disable_rps_interrupts(dev);
 }
 
 static void valleyview_disable_rps(struct drm_device *dev)
@@ -3222,6 +3244,19 @@ int intel_enable_rc6(const struct drm_device *dev)
 	return INTEL_RC6_ENABLE;
 }
 
+static void gen8_enable_rps_interrupts(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	spin_lock_irq(&dev_priv->irq_lock);
+	WARN_ON(dev_priv->rps.pm_iir);
+	bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
+	spin_unlock_irq(&dev_priv->irq_lock);
+
+	I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
+}
+
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3334,7 +3369,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
 	gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
 
-	gen6_enable_rps_interrupts(dev);
+	gen8_enable_rps_interrupts(dev);
 
 	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
-- 
1.8.5.5

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

* [PATCH 10/11] drm/i915/bdw: Enable RC6
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (8 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 09/11] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:01     ` [PATCH 11/11] drm/i915/bdw: Ensure a context is loaded before RC6 Ben Widawsky
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

It is tested and looking fairly stable now, so turn it on. It wasn't
intentionally turned off originally :P

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 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 c2980ff..a03a12e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4513,7 +4513,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		ironlake_enable_drps(dev);
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(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
-- 
1.8.5.5

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

* [PATCH 11/11] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (9 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 10/11] drm/i915/bdw: Enable RC6 Ben Widawsky
@ 2014-02-18  3:01     ` Ben Widawsky
  2014-02-18  3:03       ` [PATCH 11/11] [v2] " Ben Widawsky
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:01 UTC (permalink / raw)
  To: Intel GFX
  Cc: David E. Box, Ben Widawsky, Kristen Carlson Accardi, Ben Widawsky

RC6 works a lot like HW contexts in that when the GPU enters RC6 it
saves away the state to a context, and loads it upon wake.

It's to be somewhat expected that BIOS will not set up valid GPU state.
As a result, if loading bad state can cause the GPU to get angry, it
would make sense then that we need to load state first. There are two
ways in which we can do this:

1. Create 3d state in the driver, load it up, then enable RC6.
1b. Reuse a known good state, [and if needed,] just bind objects where
needed. Then enable RC6.
2. Hold off enabling RC6 until userspace has had a chance to complete
batches.

There has been discussions in the past with #1 as it has been
recommended for fixes elsewhere. I'm not opposed to it, I'd just like to
do the easy thing now to enable the platform.

This patch is a hack that implement option #2. It will defer enabling
rc6 until the first batch from userspace has been retired. It suffers
two flaws. The first is, if the driver is loaded, but a batch is not
submitted/completed, we'll never enter rc6. The other is, it expects
userspace to submit a batch with 3d state first. Both of these things
are not actual flaws for most users because most users will boot to a
graphical composited desktop. Both mesa, and X will always emit the
necessary 3d state.

Once a context is loaded and we enable rc6, the default context should
inherit the proper state because we always inhibit the restore for the
default context. This assumes certain things about the workaround/issue
itself to which I am not privy (primarily that the indirect state
objects don't actually need to exist).

With that, there are currently 4 options for BDW:
1. Don't use RC6.
2. Use RC6 and expect a hang on the first batch submitted for every
context.
3. Use RC6 and use this patch.
4. Wait for another workaround implementation.

NOTE: This patch could be used against other platforms as well.

The fact that RC6 residency continues to increment, and that this patch
prevents a hang on BDW silicon has been:
Tested-by: Kenneth Graunke <kenneth@whitecape.org>

Cc: David E. Box <david.e.box@intel.com>
Cc: Kristen Carlson Accardi <kristen@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_gem.c      | 12 ++++++++++++
 drivers/gpu/drm/i915/intel_display.c |  5 +++++
 drivers/gpu/drm/i915/intel_pm.c      |  2 +-
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3618bb0..07170a7 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2420,6 +2420,7 @@ void i915_gem_reset(struct drm_device *dev)
 void
 i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 {
+	static bool rc6_enabled = false;
 	uint32_t seqno;
 
 	if (list_empty(&ring->request_list))
@@ -2443,6 +2444,17 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
 			break;
 
+		/* Wa: can't find the w/a name.
+		 * This doesn't actually implement the w/a, but it a workaround
+		 * for the workaround. It defers using rc6 until we know valid
+		 * state exists.
+		 */
+		if (IS_BROADWELL(dev) && intel_enable_rc6(dev) &&
+		    !rc6_enabled && ring->id == RCS &&) {
+			intel_enable_gt_powersave(ring->dev);
+			rc6_enabled = true;
+		}
+
 		i915_gem_object_move_to_inactive(obj);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f19e6ea..72c8e1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10983,6 +10983,11 @@ void intel_modeset_init_hw(struct drm_device *dev)
 
 	intel_reset_dpio(dev);
 
+	if (IS_BROADWELL(dev)) {
+		DRM_DEBUG_DRIVER("Deferring RC6 enabling until first batch is complete\n");
+		return;
+	}
+
 	mutex_lock(&dev->struct_mutex);
 	intel_enable_gt_powersave(dev);
 	mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index a03a12e..c2980ff 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4513,7 +4513,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		ironlake_enable_drps(dev);
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
+	} else if (IS_GEN6(dev) || IS_GEN7(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
-- 
1.8.5.5

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

* [PATCH 11/11] [v2] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-02-18  3:01     ` [PATCH 11/11] drm/i915/bdw: Ensure a context is loaded before RC6 Ben Widawsky
@ 2014-02-18  3:03       ` Ben Widawsky
  2014-02-18  3:56         ` [PATCH 11/11] [v3] " Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:03 UTC (permalink / raw)
  To: Intel GFX
  Cc: David E. Box, Ben Widawsky, Kristen Carlson Accardi, Ben Widawsky

RC6 works a lot like HW contexts in that when the GPU enters RC6 it
saves away the state to a context, and loads it upon wake.

It's to be somewhat expected that BIOS will not set up valid GPU state.
As a result, if loading bad state can cause the GPU to get angry, it
would make sense then that we need to load state first. There are two
ways in which we can do this:

1. Create 3d state in the driver, load it up, then enable RC6.
1b. Reuse a known good state, [and if needed,] just bind objects where
needed. Then enable RC6.
2. Hold off enabling RC6 until userspace has had a chance to complete
batches.

There has been discussions in the past with #1 as it has been
recommended for fixes elsewhere. I'm not opposed to it, I'd just like to
do the easy thing now to enable the platform.

This patch is a hack that implement option #2. It will defer enabling
rc6 until the first batch from userspace has been retired. It suffers
two flaws. The first is, if the driver is loaded, but a batch is not
submitted/completed, we'll never enter rc6. The other is, it expects
userspace to submit a batch with 3d state first. Both of these things
are not actual flaws for most users because most users will boot to a
graphical composited desktop. Both mesa, and X will always emit the
necessary 3d state.

Once a context is loaded and we enable rc6, the default context should
inherit the proper state because we always inhibit the restore for the
default context. This assumes certain things about the workaround/issue
itself to which I am not privy (primarily that the indirect state
objects don't actually need to exist).

With that, there are currently 4 options for BDW:
1. Don't use RC6.
2. Use RC6 and expect a hang on the first batch submitted for every
context.
3. Use RC6 and use this patch.
4. Wait for another workaround implementation.

NOTE: This patch could be used against other platforms as well.

v2: Re-add accidentally dropped hunk (Ben)

The fact that RC6 residency continues to increment, and that this patch
prevents a hang on BDW silicon has been:
Tested-by: Kenneth Graunke <kenneth@whitecape.org>

Cc: David E. Box <david.e.box@intel.com>
Cc: Kristen Carlson Accardi <kristen@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_gem.c      | 12 ++++++++++++
 drivers/gpu/drm/i915/intel_display.c |  5 +++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3618bb0..07170a7 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2420,6 +2420,7 @@ void i915_gem_reset(struct drm_device *dev)
 void
 i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 {
+	static bool rc6_enabled = false;
 	uint32_t seqno;
 
 	if (list_empty(&ring->request_list))
@@ -2443,6 +2444,17 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
 			break;
 
+		/* Wa: can't find the w/a name.
+		 * This doesn't actually implement the w/a, but it a workaround
+		 * for the workaround. It defers using rc6 until we know valid
+		 * state exists.
+		 */
+		if (IS_BROADWELL(dev) && intel_enable_rc6(dev) &&
+		    !rc6_enabled && ring->id == RCS &&) {
+			intel_enable_gt_powersave(ring->dev);
+			rc6_enabled = true;
+		}
+
 		i915_gem_object_move_to_inactive(obj);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f19e6ea..72c8e1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10983,6 +10983,11 @@ void intel_modeset_init_hw(struct drm_device *dev)
 
 	intel_reset_dpio(dev);
 
+	if (IS_BROADWELL(dev)) {
+		DRM_DEBUG_DRIVER("Deferring RC6 enabling until first batch is complete\n");
+		return;
+	}
+
 	mutex_lock(&dev->struct_mutex);
 	intel_enable_gt_powersave(dev);
 	mutex_unlock(&dev->struct_mutex);
-- 
1.8.5.5

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

* [PATCH 11/11] [v3] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-02-18  3:03       ` [PATCH 11/11] [v2] " Ben Widawsky
@ 2014-02-18  3:56         ` Ben Widawsky
  2014-02-20  6:27           ` [PATCH 11/11] [v4] " Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18  3:56 UTC (permalink / raw)
  To: Intel GFX
  Cc: David E. Box, Ben Widawsky, Kristen Carlson Accardi, Ben Widawsky

RC6 works a lot like HW contexts in that when the GPU enters RC6 it
saves away the state to a context, and loads it upon wake.

It's to be somewhat expected that BIOS will not set up valid GPU state.
As a result, if loading bad state can cause the GPU to get angry, it
would make sense then that we need to load state first. There are two
ways in which we can do this:

1. Create 3d state in the driver, load it up, then enable RC6.
1b. Reuse a known good state, [and if needed,] just bind objects where
needed. Then enable RC6.
2. Hold off enabling RC6 until userspace has had a chance to complete
batches.

There has been discussions in the past with #1 as it has been
recommended for fixes elsewhere. I'm not opposed to it, I'd just like to
do the easy thing now to enable the platform.

This patch is a hack that implement option #2. It will defer enabling
rc6 until the first batch from userspace has been retired. It suffers
two flaws. The first is, if the driver is loaded, but a batch is not
submitted/completed, we'll never enter rc6. The other is, it expects
userspace to submit a batch with 3d state first. Both of these things
are not actual flaws for most users because most users will boot to a
graphical composited desktop. Both mesa, and X will always emit the
necessary 3d state.

Once a context is loaded and we enable rc6, the default context should
inherit the proper state because we always inhibit the restore for the
default context. This assumes certain things about the workaround/issue
itself to which I am not privy (primarily that the indirect state
objects don't actually need to exist).

With that, there are currently 4 options for BDW:
1. Don't use RC6.
2. Use RC6 and expect a hang on the first batch submitted for every
context.
3. Use RC6 and use this patch.
4. Wait for another workaround implementation.

NOTE: This patch could be used against other platforms as well.

v2: Re-add accidentally dropped hunk (Ben)

v3: Now more compilable (Ben)

The fact that RC6 residency continues to increment, and that this patch
prevents a hang on BDW silicon has been:
Tested-by: Kenneth Graunke <kenneth@whitecape.org>

Cc: David E. Box <david.e.box@intel.com>
Cc: Kristen Carlson Accardi <kristen@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_gem.c      | 12 ++++++++++++
 drivers/gpu/drm/i915/intel_display.c |  5 +++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3618bb0..55dca80 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2420,6 +2420,7 @@ void i915_gem_reset(struct drm_device *dev)
 void
 i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 {
+	static bool rc6_enabled = false;
 	uint32_t seqno;
 
 	if (list_empty(&ring->request_list))
@@ -2443,6 +2444,17 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
 			break;
 
+		/* Wa: can't find the w/a name.
+		 * This doesn't actually implement the w/a, but it a workaround
+		 * for the workaround. It defers using rc6 until we know valid
+		 * state exists.
+		 */
+		if (IS_BROADWELL(ring->dev) && intel_enable_rc6(ring->dev) &&
+		    !rc6_enabled && ring->id == RCS) {
+			intel_enable_gt_powersave(ring->dev);
+			rc6_enabled = true;
+		}
+
 		i915_gem_object_move_to_inactive(obj);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f19e6ea..72c8e1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10983,6 +10983,11 @@ void intel_modeset_init_hw(struct drm_device *dev)
 
 	intel_reset_dpio(dev);
 
+	if (IS_BROADWELL(dev)) {
+		DRM_DEBUG_DRIVER("Deferring RC6 enabling until first batch is complete\n");
+		return;
+	}
+
 	mutex_lock(&dev->struct_mutex);
 	intel_enable_gt_powersave(dev);
 	mutex_unlock(&dev->struct_mutex);
-- 
1.8.5.5

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

* [PATCH 03/11] [v2] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-18  3:01     ` [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
@ 2014-02-18 19:03       ` Ben Widawsky
  2014-02-22 13:37       ` [PATCH 03/11] " Chris Wilson
  1 sibling, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-18 19:03 UTC (permalink / raw)
  To: Intel GFX; +Cc: Ben Widawsky, Ben Widawsky

The names of the struct members for RPS are stupid. Every time I need to
do anything in this code I have to spend a significant amount of time to
remember what it all means. By renaming the variables (and adding the
comments) I hope to clear up the situation. Indeed doing this make some
upcoming patches more readable.

I've avoided ILK because it's possible that the naming used for Ironlake
matches what is in the docs. I believe the ILK power docs were never
published, and I am too lazy to dig them up.

While there may be mistakes, this patch was mostly done via sed. The
renaming of "hw_max" required a bit of interactivity.

v2: Updated code comments to be less repetitive and more informative
(Ben)

Cc: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  26 ++++----
 drivers/gpu/drm/i915/i915_drv.h     |  31 +++++++---
 drivers/gpu/drm/i915/i915_irq.c     |  24 ++++----
 drivers/gpu/drm/i915/i915_sysfs.c   |  44 +++++++-------
 drivers/gpu/drm/i915/intel_pm.c     | 116 ++++++++++++++++++------------------
 5 files changed, 129 insertions(+), 112 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d90a707..80087d1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1027,7 +1027,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 			   max_freq * GT_FREQUENCY_MULTIPLIER);
 
 		seq_printf(m, "Max overclocked frequency: %dMHz\n",
-			   dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER);
+			   dev_priv->rps.max_freq_overclock * GT_FREQUENCY_MULTIPLIER);
 	} else if (IS_VALLEYVIEW(dev)) {
 		u32 freq_sts, val;
 
@@ -1485,8 +1485,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 
 	seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
-	for (gpu_freq = dev_priv->rps.min_delay;
-	     gpu_freq <= dev_priv->rps.max_delay;
+	for (gpu_freq = dev_priv->rps.min_freq_softlimit;
+	     gpu_freq <= dev_priv->rps.max_freq_softlimit;
 	     gpu_freq++) {
 		ia_freq = gpu_freq;
 		sandybridge_pcode_read(dev_priv,
@@ -3371,9 +3371,9 @@ i915_max_freq_get(void *data, u64 *val)
 		return ret;
 
 	if (IS_VALLEYVIEW(dev))
-		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
+		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit);
 	else
-		*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
+		*val = dev_priv->rps.max_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -3410,16 +3410,16 @@ i915_max_freq_set(void *data, u64 val)
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq_overclock;
 		hw_min = (rp_state_cap >> 16) & 0xff;
 	}
 
-	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
+	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.max_delay = val;
+	dev_priv->rps.max_freq_softlimit = val;
 
 	if (IS_VALLEYVIEW(dev))
 		valleyview_set_rps(dev, val);
@@ -3452,9 +3452,9 @@ i915_min_freq_get(void *data, u64 *val)
 		return ret;
 
 	if (IS_VALLEYVIEW(dev))
-		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
+		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit);
 	else
-		*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
+		*val = dev_priv->rps.min_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -3491,16 +3491,16 @@ i915_min_freq_set(void *data, u64 val)
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq_overclock;
 		hw_min = (rp_state_cap >> 16) & 0xff;
 	}
 
-	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
+	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.min_delay = val;
+	dev_priv->rps.min_freq_softlimit = val;
 
 	if (IS_VALLEYVIEW(dev))
 		valleyview_set_rps(dev, val);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8c64831..90aa1c5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -967,13 +967,30 @@ struct intel_gen6_power_mgmt {
 	struct work_struct work;
 	u32 pm_iir;
 
-	u8 cur_delay;
-	u8 min_delay;
-	u8 max_delay;
-	u8 rpe_delay;
-	u8 rp1_delay;
-	u8 rp0_delay;
-	u8 hw_max;
+	/* Frequencies are stored in potentially platform dependent multiples.
+	 * In other words, *_freq needs to be multiplied by X to be interesting.
+	 * Soft limits may exist for a variety of reasons, but they can usually
+	 * be overridden through user intervention. Soft limits are used for the
+	 * dynamic reclocking done by the driver (raise frequencies under heavy
+	 * loads, and lower for lighter loads). Soft limits default to the min
+	 * and max hard limits, but can be restricted via sysfs/debugfs.
+	 *
+	 * Hard limits are actual limits imposed by the hardware.
+
+	 * A distinction is made for overclocking, which is never enabled by
+	 * default, and is considered to be above the hard limit if it's
+	 * possible at all.
+	 *
+	 * Nominal frequency is a predetermined value to give the best
+	 * performance/power ratio.
+	 */
+	u8 cur_freq; /* Current frequency (cached in SW, may not reflect HW) */
+	u8 min_freq_softlimit; /* Minimum frequency permitted by the driver */
+	u8 max_freq_softlimit; /* Max frequency permitted by the driver */
+	u8 min_freq_hardlimit; /* AKA RP1 Minimum frequency permitted by the GPU */
+	u8 max_freq_hardlimit; /* AKA RP0 Maximum frequency permitted by the GPU */
+	u8 nominal_freq; /* AKA RPn Nominal GPU frequency */
+	u8 max_freq_overclock; /* Max overclocking frequency permitted by the GPU */
 
 	bool rp_up_masked;
 	bool rp_down_masked;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f68aee3..49f2627 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1063,7 +1063,7 @@ void gen6_set_pm_mask(struct drm_i915_private *dev_priv,
 			     u32 pm_iir, int new_delay)
 {
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
-		if (new_delay >= dev_priv->rps.max_delay) {
+		if (new_delay >= dev_priv->rps.max_freq_softlimit) {
 			/* Mask UP THRESHOLD Interrupts */
 			I915_WRITE(GEN6_PMINTRMSK,
 				   I915_READ(GEN6_PMINTRMSK) |
@@ -1078,7 +1078,7 @@ void gen6_set_pm_mask(struct drm_i915_private *dev_priv,
 			dev_priv->rps.rp_down_masked = false;
 		}
 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
-		if (new_delay <= dev_priv->rps.min_delay) {
+		if (new_delay <= dev_priv->rps.min_freq_softlimit) {
 			/* Mask DOWN THRESHOLD Interrupts */
 			I915_WRITE(GEN6_PMINTRMSK,
 				   I915_READ(GEN6_PMINTRMSK) |
@@ -1124,38 +1124,38 @@ static void gen6_pm_rps_work(struct work_struct *work)
 			adj *= 2;
 		else
 			adj = 1;
-		new_delay = dev_priv->rps.cur_delay + adj;
+		new_delay = dev_priv->rps.cur_freq + adj;
 
 		/*
 		 * For better performance, jump directly
 		 * to RPe if we're below it.
 		 */
-		if (new_delay < dev_priv->rps.rpe_delay)
-			new_delay = dev_priv->rps.rpe_delay;
+		if (new_delay < dev_priv->rps.nominal_freq)
+			new_delay = dev_priv->rps.nominal_freq;
 	} else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) {
-		if (dev_priv->rps.cur_delay > dev_priv->rps.rpe_delay)
-			new_delay = dev_priv->rps.rpe_delay;
+		if (dev_priv->rps.cur_freq > dev_priv->rps.nominal_freq)
+			new_delay = dev_priv->rps.nominal_freq;
 		else
-			new_delay = dev_priv->rps.min_delay;
+			new_delay = dev_priv->rps.min_freq_softlimit;
 		adj = 0;
 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
 		if (adj < 0)
 			adj *= 2;
 		else
 			adj = -1;
-		new_delay = dev_priv->rps.cur_delay + adj;
+		new_delay = dev_priv->rps.cur_freq + adj;
 	} else { /* unknown event */
-		new_delay = dev_priv->rps.cur_delay;
+		new_delay = dev_priv->rps.cur_freq;
 	}
 
 	/* sysfs frequency interfaces may have snuck in while servicing the
 	 * interrupt
 	 */
 	new_delay = clamp_t(int, new_delay,
-			    dev_priv->rps.min_delay, dev_priv->rps.max_delay);
+			    dev_priv->rps.min_freq_softlimit, dev_priv->rps.max_freq_softlimit);
 
 	gen6_set_pm_mask(dev_priv, pm_iir, new_delay);
-	dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
+	dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_freq;
 
 	if (IS_VALLEYVIEW(dev_priv->dev))
 		valleyview_set_rps(dev_priv->dev, new_delay);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e9ffefb..86999aa 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -269,7 +269,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 		freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
 		ret = vlv_gpu_freq(dev_priv, (freq >> 8) & 0xff);
 	} else {
-		ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.cur_freq * GT_FREQUENCY_MULTIPLIER;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
@@ -284,7 +284,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-			vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay));
+			vlv_gpu_freq(dev_priv, dev_priv->rps.nominal_freq));
 }
 
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -298,9 +298,9 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (IS_VALLEYVIEW(dev_priv->dev))
-		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
+		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit);
 	else
-		ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.max_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -334,13 +334,13 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		val /= GT_FREQUENCY_MULTIPLIER;
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq_overclock;
 		non_oc_max = (rp_state_cap & 0xff);
 		hw_min = ((rp_state_cap & 0xff0000) >> 16);
 	}
 
 	if (val < hw_min || val > hw_max ||
-	    val < dev_priv->rps.min_delay) {
+	    val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
@@ -349,18 +349,18 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		DRM_DEBUG("User requested overclocking to %d\n",
 			  val * GT_FREQUENCY_MULTIPLIER);
 
-	dev_priv->rps.max_delay = val;
+	dev_priv->rps.max_freq_softlimit = val;
 
-	if (dev_priv->rps.cur_delay > val) {
+	if (dev_priv->rps.cur_freq > val) {
 		if (IS_VALLEYVIEW(dev))
 			valleyview_set_rps(dev, val);
 		else
 			gen6_set_rps(dev, val);
 	} else if (!IS_VALLEYVIEW(dev)) {
-		/* We still need gen6_set_rps to process the new max_delay and
-		 * update the interrupt limits even though frequency request is
-		 * unchanged. */
-		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+		/* We still need gen6_set_rps to process the new
+		 * max_freq_softlimit and update the interrupt limits even
+		 * though frequency request is unchanged. */
+		gen6_set_rps(dev, dev_priv->rps.cur_freq);
 	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -379,9 +379,9 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (IS_VALLEYVIEW(dev_priv->dev))
-		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
+		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit);
 	else
-		ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.min_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -414,27 +414,27 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 		val /= GT_FREQUENCY_MULTIPLIER;
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq_overclock;
 		hw_min = ((rp_state_cap & 0xff0000) >> 16);
 	}
 
-	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
+	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.min_delay = val;
+	dev_priv->rps.min_freq_softlimit = val;
 
-	if (dev_priv->rps.cur_delay < val) {
+	if (dev_priv->rps.cur_freq < val) {
 		if (IS_VALLEYVIEW(dev))
 			valleyview_set_rps(dev, val);
 		else
 			gen6_set_rps(dev, val);
 	} else if (!IS_VALLEYVIEW(dev)) {
-		/* We still need gen6_set_rps to process the new min_delay and
-		 * update the interrupt limits even though frequency request is
-		 * unchanged. */
-		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+		/* We still need gen6_set_rps to process the new
+		 * min_freq_softlimit and update the interrupt limits even
+		 * though frequency request is unchanged. */
+		gen6_set_rps(dev, dev_priv->rps.cur_freq);
 	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 66172b6..341c154 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2904,9 +2904,9 @@ static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 val)
 	 * the hw runs at the minimal clock before selecting the desired
 	 * frequency, if the down threshold expires in that window we will not
 	 * receive a down interrupt. */
-	limits = dev_priv->rps.max_delay << 24;
-	if (val <= dev_priv->rps.min_delay)
-		limits |= dev_priv->rps.min_delay << 16;
+	limits = dev_priv->rps.max_freq_softlimit << 24;
+	if (val <= dev_priv->rps.min_freq_softlimit)
+		limits |= dev_priv->rps.min_freq_softlimit << 16;
 
 	return limits;
 }
@@ -2918,26 +2918,26 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 	new_power = dev_priv->rps.power;
 	switch (dev_priv->rps.power) {
 	case LOW_POWER:
-		if (val > dev_priv->rps.rpe_delay + 1 && val > dev_priv->rps.cur_delay)
+		if (val > dev_priv->rps.nominal_freq + 1 && val > dev_priv->rps.cur_freq)
 			new_power = BETWEEN;
 		break;
 
 	case BETWEEN:
-		if (val <= dev_priv->rps.rpe_delay && val < dev_priv->rps.cur_delay)
+		if (val <= dev_priv->rps.nominal_freq && val < dev_priv->rps.cur_freq)
 			new_power = LOW_POWER;
-		else if (val >= dev_priv->rps.rp0_delay && val > dev_priv->rps.cur_delay)
+		else if (val >= dev_priv->rps.max_freq_hardlimit && val > dev_priv->rps.cur_freq)
 			new_power = HIGH_POWER;
 		break;
 
 	case HIGH_POWER:
-		if (val < (dev_priv->rps.rp1_delay + dev_priv->rps.rp0_delay) >> 1 && val < dev_priv->rps.cur_delay)
+		if (val < (dev_priv->rps.min_freq_hardlimit + dev_priv->rps.max_freq_hardlimit) >> 1 && val < dev_priv->rps.cur_freq)
 			new_power = BETWEEN;
 		break;
 	}
 	/* Max/min bins are special */
-	if (val == dev_priv->rps.min_delay)
+	if (val == dev_priv->rps.min_freq_softlimit)
 		new_power = LOW_POWER;
-	if (val == dev_priv->rps.max_delay)
+	if (val == dev_priv->rps.max_freq_softlimit)
 		new_power = HIGH_POWER;
 	if (new_power == dev_priv->rps.power)
 		return;
@@ -3004,17 +3004,17 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 }
 
 /* gen6_set_rps is called to update the frequency request, but should also be
- * called when the range (min_delay and max_delay) is modified so that we can
+ * called when the range (min_freq_softlimit and max_freq_softlimit) is modified so that we can
  * update the GEN6_RP_INTERRUPT_LIMITS register accordingly. */
 void gen6_set_rps(struct drm_device *dev, u8 val)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-	WARN_ON(val > dev_priv->rps.max_delay);
-	WARN_ON(val < dev_priv->rps.min_delay);
+	WARN_ON(val > dev_priv->rps.max_freq_softlimit);
+	WARN_ON(val < dev_priv->rps.min_freq_softlimit);
 
-	if (val == dev_priv->rps.cur_delay) {
+	if (val == dev_priv->rps.cur_freq) {
 		/* min/max delay may still have been modified so be sure to
 		 * write the limits value */
 		I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
@@ -3042,7 +3042,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 
 	POSTING_READ(GEN6_RPNSWREQ);
 
-	dev_priv->rps.cur_delay = val;
+	dev_priv->rps.cur_freq = val;
 
 	trace_intel_gpu_freq_change(val * 50);
 }
@@ -3062,7 +3062,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 	 * When we are idle.  Drop to min voltage state.
 	 */
 
-	if (dev_priv->rps.cur_delay <= dev_priv->rps.min_delay)
+	if (dev_priv->rps.cur_freq <= dev_priv->rps.min_freq_softlimit)
 		return;
 
 	/* Mask turbo interrupt so that they will not come in between */
@@ -3079,10 +3079,10 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 		return;
 	}
 
-	dev_priv->rps.cur_delay = dev_priv->rps.min_delay;
+	dev_priv->rps.cur_freq = dev_priv->rps.min_freq_softlimit;
 
 	vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ,
-					dev_priv->rps.min_delay);
+					dev_priv->rps.min_freq_softlimit);
 
 	if (wait_for(((vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS))
 				& GENFREQSTATUS) == 0, 5))
@@ -3096,7 +3096,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 	/* Unmask Up interrupts */
 	dev_priv->rps.rp_up_masked = true;
 	gen6_set_pm_mask(dev_priv, GEN6_PM_RP_DOWN_THRESHOLD,
-						dev_priv->rps.min_delay);
+						dev_priv->rps.min_freq_softlimit);
 }
 
 void gen6_rps_idle(struct drm_i915_private *dev_priv)
@@ -3108,7 +3108,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
 		if (IS_VALLEYVIEW(dev))
 			vlv_set_rps_idle(dev_priv);
 		else
-			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
+			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
 		dev_priv->rps.last_adj = 0;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -3121,9 +3121,9 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv)
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (dev_priv->rps.enabled) {
 		if (IS_VALLEYVIEW(dev))
-			valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
+			valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit);
 		else
-			gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
+			gen6_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit);
 		dev_priv->rps.last_adj = 0;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -3134,20 +3134,20 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-	WARN_ON(val > dev_priv->rps.max_delay);
-	WARN_ON(val < dev_priv->rps.min_delay);
+	WARN_ON(val > dev_priv->rps.max_freq_softlimit);
+	WARN_ON(val < dev_priv->rps.min_freq_softlimit);
 
 	DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
-			 dev_priv->rps.cur_delay,
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
+			 dev_priv->rps.cur_freq,
 			 vlv_gpu_freq(dev_priv, val), val);
 
-	if (val == dev_priv->rps.cur_delay)
+	if (val == dev_priv->rps.cur_freq)
 		return;
 
 	vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val);
 
-	dev_priv->rps.cur_delay = val;
+	dev_priv->rps.cur_freq = val;
 
 	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
@@ -3289,8 +3289,8 @@ static void gen8_enable_rps(struct drm_device *dev)
 
 	/* Docs recommend 900MHz, and 300 MHz respectively */
 	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
-		   dev_priv->rps.max_delay << 24 |
-		   dev_priv->rps.min_delay << 16);
+		   dev_priv->rps.max_freq_softlimit << 24 |
+		   dev_priv->rps.min_freq_softlimit << 16);
 
 	I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */
 	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/
@@ -3350,19 +3350,19 @@ static void gen6_enable_rps(struct drm_device *dev)
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
 	/* In units of 50MHz */
-	dev_priv->rps.hw_max = hw_max = rp_state_cap & 0xff;
+	dev_priv->rps.max_freq_overclock = hw_max = rp_state_cap & 0xff;
 	hw_min = (rp_state_cap >> 16) & 0xff;
-	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
-	dev_priv->rps.cur_delay = 0;
+	dev_priv->rps.min_freq_hardlimit = (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.max_freq_hardlimit = (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.nominal_freq = dev_priv->rps.min_freq_hardlimit;
+	dev_priv->rps.cur_freq = 0;
 
 	/* Preserve min/max settings in case of re-init */
-	if (dev_priv->rps.max_delay == 0)
-		dev_priv->rps.max_delay = hw_max;
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = hw_max;
 
-	if (dev_priv->rps.min_delay == 0)
-		dev_priv->rps.min_delay = hw_min;
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = hw_min;
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -3417,13 +3417,13 @@ static void gen6_enable_rps(struct drm_device *dev)
 	ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
 	if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
 		DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
-				 (dev_priv->rps.max_delay & 0xff) * 50,
+				 (dev_priv->rps.max_freq_softlimit & 0xff) * 50,
 				 (pcu_mbox & 0xff) * 50);
-		dev_priv->rps.hw_max = pcu_mbox & 0xff;
+		dev_priv->rps.max_freq_overclock = pcu_mbox & 0xff;
 	}
 
 	dev_priv->rps.power = HIGH_POWER; /* force a reset */
-	gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
+	gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
 
 	gen6_enable_rps_interrupts(dev);
 
@@ -3479,9 +3479,9 @@ void gen6_update_ring_freq(struct drm_device *dev)
 	 * to use for memory access.  We do this by specifying the IA frequency
 	 * the PCU should use as a reference to determine the ring frequency.
 	 */
-	for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay;
+	for (gpu_freq = dev_priv->rps.max_freq_softlimit; gpu_freq >= dev_priv->rps.min_freq_softlimit;
 	     gpu_freq--) {
-		int diff = dev_priv->rps.max_delay - gpu_freq;
+		int diff = dev_priv->rps.max_freq_softlimit - gpu_freq;
 		unsigned int ia_freq = 0, ring_freq = 0;
 
 		if (INTEL_INFO(dev)->gen >= 8) {
@@ -3647,20 +3647,20 @@ static void valleyview_enable_rps(struct drm_device *dev)
 	DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
 	DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
 
-	dev_priv->rps.cur_delay = (val >> 8) & 0xff;
+	dev_priv->rps.cur_freq = (val >> 8) & 0xff;
 	DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
-			 dev_priv->rps.cur_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
+			 dev_priv->rps.cur_freq);
 
-	dev_priv->rps.hw_max = hw_max = valleyview_rps_max_freq(dev_priv);
+	dev_priv->rps.max_freq_overclock = hw_max = valleyview_rps_max_freq(dev_priv);
 	DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
 			 vlv_gpu_freq(dev_priv, hw_max),
 			 hw_max);
 
-	dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv);
+	dev_priv->rps.nominal_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.rpe_delay),
-			 dev_priv->rps.rpe_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.nominal_freq),
+			 dev_priv->rps.nominal_freq);
 
 	hw_min = valleyview_rps_min_freq(dev_priv);
 	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
@@ -3668,17 +3668,17 @@ static void valleyview_enable_rps(struct drm_device *dev)
 			 hw_min);
 
 	/* Preserve min/max settings in case of re-init */
-	if (dev_priv->rps.max_delay == 0)
-		dev_priv->rps.max_delay = hw_max;
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = hw_max;
 
-	if (dev_priv->rps.min_delay == 0)
-		dev_priv->rps.min_delay = hw_min;
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = hw_min;
 
 	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
-			 dev_priv->rps.rpe_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.nominal_freq),
+			 dev_priv->rps.nominal_freq);
 
-	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
+	valleyview_set_rps(dev_priv->dev, dev_priv->rps.nominal_freq);
 
 	dev_priv->rps.rp_up_masked = false;
 	dev_priv->rps.rp_down_masked = false;
@@ -4119,7 +4119,7 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
 
 	assert_spin_locked(&mchdev_lock);
 
-	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_delay * 4));
+	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_freq * 4));
 	pxvid = (pxvid >> 24) & 0x7f;
 	ext_v = pvid_to_extvid(dev_priv, pxvid);
 
-- 
1.9.0

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

* [PATCH 11/11] [v4] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-02-18  3:56         ` [PATCH 11/11] [v3] " Ben Widawsky
@ 2014-02-20  6:27           ` Ben Widawsky
  2014-03-04 14:30             ` Daniel Vetter
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-02-20  6:27 UTC (permalink / raw)
  To: Intel GFX
  Cc: David E. Box, Ben Widawsky, Kristen Carlson Accardi, Ben Widawsky

RC6 works a lot like HW contexts in that when the GPU enters RC6 it
saves away the state to a context, and loads it upon wake.

It's to be somewhat expected that BIOS will not set up valid GPU state.
As a result, if loading bad state can cause the GPU to get angry, it
would make sense then that we need to load state first. There are two
ways in which we can do this:

1. Create 3d state in the driver, load it up, then enable RC6.
1b. Reuse a known good state, [and if needed,] just bind objects where
needed. Then enable RC6.
2. Hold off enabling RC6 until userspace has had a chance to complete
batches.

There has been discussions in the past with #1 as it has been
recommended for fixes elsewhere. I'm not opposed to it, I'd just like to
do the easy thing now to enable the platform.

This patch is a hack that implement option #2. It will defer enabling
rc6 until the first batch from userspace has been retired. It suffers
two flaws. The first is, if the driver is loaded, but a batch is not
submitted/completed, we'll never enter rc6. The other is, it expects
userspace to submit a batch with 3d state first. Both of these things
are not actual flaws for most users because most users will boot to a
graphical composited desktop. Both mesa, and X will always emit the
necessary 3d state.

Once a context is loaded and we enable rc6, the default context should
inherit the proper state because we always inhibit the restore for the
default context. This assumes certain things about the workaround/issue
itself to which I am not privy (primarily that the indirect state
objects don't actually need to exist).

With that, there are currently 4 options for BDW:
1. Don't use RC6.
2. Use RC6 and expect a hang on the first batch submitted for every
context.
3. Use RC6 and use this patch.
4. Wait for another workaround implementation.

NOTE: This patch could be used against other platforms as well.

v2: Re-add accidentally dropped hunk (Ben)

v3: Now more compilable (Ben)

v4: Use the existing enable flag for rc6. This will also make the
suspend/resume case work properly, which is broken in v3.
Disable rc6 on reset, and defer re-enabling until the first batch.

The fact that RC6 residency continues to increment, and that this patch
prevents a hang on BDW silicon has been:
Tested-by: Kenneth Graunke <kenneth@whitecape.org> (v1)

Cc: David E. Box <david.e.box@intel.com>
Cc: Kristen Carlson Accardi <kristen@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>

squash! drm/i915/bdw: Ensure a context is loaded before RC6
---
 drivers/gpu/drm/i915/i915_drv.c      |  4 +++-
 drivers/gpu/drm/i915/i915_gem.c      | 10 ++++++++++
 drivers/gpu/drm/i915/intel_display.c |  5 +++++
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 2d05d7c..7fdfc0e 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -679,6 +679,8 @@ int i915_reset(struct drm_device *dev)
 	mutex_lock(&dev->struct_mutex);
 
 	i915_gem_reset(dev);
+	if (IS_BROADWELL(dev))
+		intel_disable_gt_powersave(dev);
 
 	simulated = dev_priv->gpu_error.stop_rings != 0;
 
@@ -733,7 +735,7 @@ 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) {
+		if (INTEL_INFO(dev)->gen > 5 && !IS_BROADWELL(dev)) {
 			mutex_lock(&dev->struct_mutex);
 			intel_enable_gt_powersave(dev);
 			mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3618bb0..25a97a6 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2420,6 +2420,7 @@ void i915_gem_reset(struct drm_device *dev)
 void
 i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 {
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	uint32_t seqno;
 
 	if (list_empty(&ring->request_list))
@@ -2443,6 +2444,15 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
 			break;
 
+		/* Wa: can't find the w/a name.
+		 * This doesn't actually implement the w/a, but it a workaround
+		 * for the workaround. It defers using rc6 until we know valid
+		 * state exists.
+		 */
+		if (IS_BROADWELL(ring->dev) && intel_enable_rc6(ring->dev) &&
+		    !dev_priv->rps.enabled && ring->id == RCS)
+			intel_enable_gt_powersave(ring->dev);
+
 		i915_gem_object_move_to_inactive(obj);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f19e6ea..72c8e1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10983,6 +10983,11 @@ void intel_modeset_init_hw(struct drm_device *dev)
 
 	intel_reset_dpio(dev);
 
+	if (IS_BROADWELL(dev)) {
+		DRM_DEBUG_DRIVER("Deferring RC6 enabling until first batch is complete\n");
+		return;
+	}
+
 	mutex_lock(&dev->struct_mutex);
 	intel_enable_gt_powersave(dev);
 	mutex_unlock(&dev->struct_mutex);
-- 
1.9.0

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-18  3:01     ` [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
  2014-02-18 19:03       ` [PATCH 03/11] [v2] " Ben Widawsky
@ 2014-02-22 13:37       ` Chris Wilson
  2014-02-22 19:34         ` Ben Widawsky
  2014-03-19  1:27         ` Ben Widawsky
  1 sibling, 2 replies; 97+ messages in thread
From: Chris Wilson @ 2014-02-22 13:37 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Ben Widawsky

On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> The names of the struct members for RPS are stupid. Every time I need to
> do anything in this code I have to spend a significant amount of time to
> remember what it all means. By renaming the variables (and adding the
> comments) I hope to clear up the situation. Indeed doing this make some
> upcoming patches more readable.
> 
> I've avoided ILK because it's possible that the naming used for Ironlake
> matches what is in the docs. I believe the ILK power docs were never
> published, and I am too lazy to dig them up.
> 
> While there may be mistakes, this patch was mostly done via sed. The
> renaming of "hw_max" required a bit of interactivity.

It lost the distinction between RPe and RPn. I am in favour of keeping
RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
soft values used for actual interaction.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-22 13:37       ` [PATCH 03/11] " Chris Wilson
@ 2014-02-22 19:34         ` Ben Widawsky
  2014-02-22 19:37           ` Chris Wilson
  2014-02-22 19:38           ` Ben Widawsky
  2014-03-19  1:27         ` Ben Widawsky
  1 sibling, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-22 19:34 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Intel GFX

On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > The names of the struct members for RPS are stupid. Every time I need to
> > do anything in this code I have to spend a significant amount of time to
> > remember what it all means. By renaming the variables (and adding the
> > comments) I hope to clear up the situation. Indeed doing this make some
> > upcoming patches more readable.
> > 
> > I've avoided ILK because it's possible that the naming used for Ironlake
> > matches what is in the docs. I believe the ILK power docs were never
> > published, and I am too lazy to dig them up.
> > 
> > While there may be mistakes, this patch was mostly done via sed. The
> > renaming of "hw_max" required a bit of interactivity.
> 
> It lost the distinction between RPe and RPn. I am in favour of keeping
> RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> soft values used for actual interaction.
> -Chris
> 

And what is the difference between RPe, and RPn? I honestly have no clue
what RPe is.

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-22 19:34         ` Ben Widawsky
@ 2014-02-22 19:37           ` Chris Wilson
  2014-02-22 19:40             ` Ben Widawsky
  2014-02-22 19:38           ` Ben Widawsky
  1 sibling, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2014-02-22 19:37 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Ben Widawsky

On Sat, Feb 22, 2014 at 11:34:16AM -0800, Ben Widawsky wrote:
> On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> > On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > > The names of the struct members for RPS are stupid. Every time I need to
> > > do anything in this code I have to spend a significant amount of time to
> > > remember what it all means. By renaming the variables (and adding the
> > > comments) I hope to clear up the situation. Indeed doing this make some
> > > upcoming patches more readable.
> > > 
> > > I've avoided ILK because it's possible that the naming used for Ironlake
> > > matches what is in the docs. I believe the ILK power docs were never
> > > published, and I am too lazy to dig them up.
> > > 
> > > While there may be mistakes, this patch was mostly done via sed. The
> > > renaming of "hw_max" required a bit of interactivity.
> > 
> > It lost the distinction between RPe and RPn. I am in favour of keeping
> > RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> > soft values used for actual interaction.
> > -Chris
> > 
> 
> And what is the difference between RPe, and RPn? I honestly have no clue
> what RPe is.

It's a mythical beast on Valleyview for an inflection point in the
power/performance curve that the hardware designers recommend using.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-22 19:34         ` Ben Widawsky
  2014-02-22 19:37           ` Chris Wilson
@ 2014-02-22 19:38           ` Ben Widawsky
  2014-02-22 20:14             ` Chris Wilson
  1 sibling, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-02-22 19:38 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Intel GFX

On Sat, Feb 22, 2014 at 11:34:16AM -0800, Ben Widawsky wrote:
> On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> > On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > > The names of the struct members for RPS are stupid. Every time I need to
> > > do anything in this code I have to spend a significant amount of time to
> > > remember what it all means. By renaming the variables (and adding the
> > > comments) I hope to clear up the situation. Indeed doing this make some
> > > upcoming patches more readable.
> > > 
> > > I've avoided ILK because it's possible that the naming used for Ironlake
> > > matches what is in the docs. I believe the ILK power docs were never
> > > published, and I am too lazy to dig them up.
> > > 
> > > While there may be mistakes, this patch was mostly done via sed. The
> > > renaming of "hw_max" required a bit of interactivity.
> > 
> > It lost the distinction between RPe and RPn. I am in favour of keeping
> > RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> > soft values used for actual interaction.
> > -Chris
> > 
> 
> And what is the difference between RPe, and RPn? I honestly have no clue
> what RPe is.
> 

I sent too soon. One other thing I want to make clear with a patch [like
this] is what the min and max values always are. Names RP0, and RP1,
while matching the spec do not do this. They have no meaning to anyone
not well versed in the spec.

When one wants to find out min/max, or rp0/rp1, they'd always have to do
a conversion from one to the other by looking at the code (unless we
added a #define or something to alias it). My point really is, it's
almost always more useful to know MIN and MAX, and if you must figure
out if it's RP0, or RP1, then go back to the code to find it.


Still would like an answer about RPe...

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-22 19:37           ` Chris Wilson
@ 2014-02-22 19:40             ` Ben Widawsky
  2014-02-22 20:08               ` Chris Wilson
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-02-22 19:40 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Intel GFX

On Sat, Feb 22, 2014 at 07:37:04PM +0000, Chris Wilson wrote:
> On Sat, Feb 22, 2014 at 11:34:16AM -0800, Ben Widawsky wrote:
> > On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> > > On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > > > The names of the struct members for RPS are stupid. Every time I need to
> > > > do anything in this code I have to spend a significant amount of time to
> > > > remember what it all means. By renaming the variables (and adding the
> > > > comments) I hope to clear up the situation. Indeed doing this make some
> > > > upcoming patches more readable.
> > > > 
> > > > I've avoided ILK because it's possible that the naming used for Ironlake
> > > > matches what is in the docs. I believe the ILK power docs were never
> > > > published, and I am too lazy to dig them up.
> > > > 
> > > > While there may be mistakes, this patch was mostly done via sed. The
> > > > renaming of "hw_max" required a bit of interactivity.
> > > 
> > > It lost the distinction between RPe and RPn. I am in favour of keeping
> > > RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> > > soft values used for actual interaction.
> > > -Chris
> > > 
> > 
> > And what is the difference between RPe, and RPn? I honestly have no clue
> > what RPe is.
> 
> It's a mythical beast on Valleyview for an inflection point in the
> power/performance curve that the hardware designers recommend using.
> -Chris
> 

Isn't that exactly what RPn is supposed to be?

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-22 19:40             ` Ben Widawsky
@ 2014-02-22 20:08               ` Chris Wilson
  2014-02-25  0:54                 ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2014-02-22 20:08 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Ben Widawsky

On Sat, Feb 22, 2014 at 11:40:43AM -0800, Ben Widawsky wrote:
> On Sat, Feb 22, 2014 at 07:37:04PM +0000, Chris Wilson wrote:
> > On Sat, Feb 22, 2014 at 11:34:16AM -0800, Ben Widawsky wrote:
> > > On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> > > > On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > > > > The names of the struct members for RPS are stupid. Every time I need to
> > > > > do anything in this code I have to spend a significant amount of time to
> > > > > remember what it all means. By renaming the variables (and adding the
> > > > > comments) I hope to clear up the situation. Indeed doing this make some
> > > > > upcoming patches more readable.
> > > > > 
> > > > > I've avoided ILK because it's possible that the naming used for Ironlake
> > > > > matches what is in the docs. I believe the ILK power docs were never
> > > > > published, and I am too lazy to dig them up.
> > > > > 
> > > > > While there may be mistakes, this patch was mostly done via sed. The
> > > > > renaming of "hw_max" required a bit of interactivity.
> > > > 
> > > > It lost the distinction between RPe and RPn. I am in favour of keeping
> > > > RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> > > > soft values used for actual interaction.
> > > > -Chris
> > > > 
> > > 
> > > And what is the difference between RPe, and RPn? I honestly have no clue
> > > what RPe is.
> > 
> > It's a mythical beast on Valleyview for an inflection point in the
> > power/performance curve that the hardware designers recommend using.
> > -Chris
> > 
> 
> Isn't that exactly what RPn is supposed to be?

No, RPn is as low as they allow the hardware to drop the frequency. RPe
was a different beast for power-efficient rendering. As usual it comes
without a single piece of substantiating or verifiable piece of
evidence, nor even if it applies to Linux workloads. Yet it is lore that
we are expected to follow on faith.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-22 19:38           ` Ben Widawsky
@ 2014-02-22 20:14             ` Chris Wilson
  0 siblings, 0 replies; 97+ messages in thread
From: Chris Wilson @ 2014-02-22 20:14 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Ben Widawsky

On Sat, Feb 22, 2014 at 11:38:55AM -0800, Ben Widawsky wrote:
> On Sat, Feb 22, 2014 at 11:34:16AM -0800, Ben Widawsky wrote:
> > On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> > > On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > > > The names of the struct members for RPS are stupid. Every time I need to
> > > > do anything in this code I have to spend a significant amount of time to
> > > > remember what it all means. By renaming the variables (and adding the
> > > > comments) I hope to clear up the situation. Indeed doing this make some
> > > > upcoming patches more readable.
> > > > 
> > > > I've avoided ILK because it's possible that the naming used for Ironlake
> > > > matches what is in the docs. I believe the ILK power docs were never
> > > > published, and I am too lazy to dig them up.
> > > > 
> > > > While there may be mistakes, this patch was mostly done via sed. The
> > > > renaming of "hw_max" required a bit of interactivity.
> > > 
> > > It lost the distinction between RPe and RPn. I am in favour of keeping
> > > RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> > > soft values used for actual interaction.
> > > -Chris
> > > 
> > 
> > And what is the difference between RPe, and RPn? I honestly have no clue
> > what RPe is.
> > 
> 
> I sent too soon. One other thing I want to make clear with a patch [like
> this] is what the min and max values always are. Names RP0, and RP1,
> while matching the spec do not do this. They have no meaning to anyone
> not well versed in the spec.
> 
> When one wants to find out min/max, or rp0/rp1, they'd always have to do
> a conversion from one to the other by looking at the code (unless we
> added a #define or something to alias it). My point really is, it's
> almost always more useful to know MIN and MAX, and if you must figure
> out if it's RP0, or RP1, then go back to the code to find it.

Right, I think we can have both. We can have RPx for the values we read
out of registers since we often have the spec open at the same time. And
from those we can store a second set of derived values that make sense
for implementing algorithms

That way, it should be easy enough to match what we see in the spec to
the limits we find and how they are transformed into human readable
values, both for exposing to userspace and for driving the gpufreq
algorithms.

It also means that we can place sanity checks at the end that we are
still within the original hw limits.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-22 20:08               ` Chris Wilson
@ 2014-02-25  0:54                 ` Ben Widawsky
  0 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-02-25  0:54 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Intel GFX

On Sat, Feb 22, 2014 at 08:08:23PM +0000, Chris Wilson wrote:
> On Sat, Feb 22, 2014 at 11:40:43AM -0800, Ben Widawsky wrote:
> > On Sat, Feb 22, 2014 at 07:37:04PM +0000, Chris Wilson wrote:
> > > On Sat, Feb 22, 2014 at 11:34:16AM -0800, Ben Widawsky wrote:
> > > > On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> > > > > On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > > > > > The names of the struct members for RPS are stupid. Every time I need to
> > > > > > do anything in this code I have to spend a significant amount of time to
> > > > > > remember what it all means. By renaming the variables (and adding the
> > > > > > comments) I hope to clear up the situation. Indeed doing this make some
> > > > > > upcoming patches more readable.
> > > > > > 
> > > > > > I've avoided ILK because it's possible that the naming used for Ironlake
> > > > > > matches what is in the docs. I believe the ILK power docs were never
> > > > > > published, and I am too lazy to dig them up.
> > > > > > 
> > > > > > While there may be mistakes, this patch was mostly done via sed. The
> > > > > > renaming of "hw_max" required a bit of interactivity.
> > > > > 
> > > > > It lost the distinction between RPe and RPn. I am in favour of keeping
> > > > > RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> > > > > soft values used for actual interaction.
> > > > > -Chris
> > > > > 
> > > > 
> > > > And what is the difference between RPe, and RPn? I honestly have no clue
> > > > what RPe is.
> > > 
> > > It's a mythical beast on Valleyview for an inflection point in the
> > > power/performance curve that the hardware designers recommend using.
> > > -Chris
> > > 
> > 
> > Isn't that exactly what RPn is supposed to be?
> 
> No, RPn is as low as they allow the hardware to drop the frequency. RPe
> was a different beast for power-efficient rendering. As usual it comes
> without a single piece of substantiating or verifiable piece of
> evidence, nor even if it applies to Linux workloads. Yet it is lore that
> we are expected to follow on faith.
> -Chris

Indeed you are right. I somehow came to believe RPe was equal to RPn,
but I have one platform where RPn is less than RP1, which would mean
that the preferred frequency is lower than the min frequency... so let
me try to fix up the patch based on the comment from the other mail. I
still aim to kill off RP* as much as possible.

> 
> -- 
> Chris Wilson, Intel Open Source Technology Centre

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 11/11] [v4] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-02-20  6:27           ` [PATCH 11/11] [v4] " Ben Widawsky
@ 2014-03-04 14:30             ` Daniel Vetter
  2014-03-20  0:41               ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2014-03-04 14:30 UTC (permalink / raw)
  To: Ben Widawsky
  Cc: David E. Box, Intel GFX, Ben Widawsky, Kristen Carlson Accardi

On Wed, Feb 19, 2014 at 10:27:20PM -0800, Ben Widawsky wrote:
> RC6 works a lot like HW contexts in that when the GPU enters RC6 it
> saves away the state to a context, and loads it upon wake.
> 
> It's to be somewhat expected that BIOS will not set up valid GPU state.
> As a result, if loading bad state can cause the GPU to get angry, it
> would make sense then that we need to load state first. There are two
> ways in which we can do this:
> 
> 1. Create 3d state in the driver, load it up, then enable RC6.
> 1b. Reuse a known good state, [and if needed,] just bind objects where
> needed. Then enable RC6.
> 2. Hold off enabling RC6 until userspace has had a chance to complete
> batches.
> 
> There has been discussions in the past with #1 as it has been
> recommended for fixes elsewhere. I'm not opposed to it, I'd just like to
> do the easy thing now to enable the platform.
> 
> This patch is a hack that implement option #2. It will defer enabling
> rc6 until the first batch from userspace has been retired. It suffers
> two flaws. The first is, if the driver is loaded, but a batch is not
> submitted/completed, we'll never enter rc6. The other is, it expects
> userspace to submit a batch with 3d state first. Both of these things
> are not actual flaws for most users because most users will boot to a
> graphical composited desktop. Both mesa, and X will always emit the
> necessary 3d state.
> 
> Once a context is loaded and we enable rc6, the default context should
> inherit the proper state because we always inhibit the restore for the
> default context. This assumes certain things about the workaround/issue
> itself to which I am not privy (primarily that the indirect state
> objects don't actually need to exist).
> 
> With that, there are currently 4 options for BDW:
> 1. Don't use RC6.
> 2. Use RC6 and expect a hang on the first batch submitted for every
> context.
> 3. Use RC6 and use this patch.
> 4. Wait for another workaround implementation.
> 
> NOTE: This patch could be used against other platforms as well.
> 
> v2: Re-add accidentally dropped hunk (Ben)
> 
> v3: Now more compilable (Ben)
> 
> v4: Use the existing enable flag for rc6. This will also make the
> suspend/resume case work properly, which is broken in v3.
> Disable rc6 on reset, and defer re-enabling until the first batch.
> 
> The fact that RC6 residency continues to increment, and that this patch
> prevents a hang on BDW silicon has been:
> Tested-by: Kenneth Graunke <kenneth@whitecape.org> (v1)
> 
> Cc: David E. Box <david.e.box@intel.com>
> Cc: Kristen Carlson Accardi <kristen@linux.intel.com>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> 
> squash! drm/i915/bdw: Ensure a context is loaded before RC6
> ---
>  drivers/gpu/drm/i915/i915_drv.c      |  4 +++-
>  drivers/gpu/drm/i915/i915_gem.c      | 10 ++++++++++
>  drivers/gpu/drm/i915/intel_display.c |  5 +++++
>  3 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 2d05d7c..7fdfc0e 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -679,6 +679,8 @@ int i915_reset(struct drm_device *dev)
>  	mutex_lock(&dev->struct_mutex);
>  
>  	i915_gem_reset(dev);
> +	if (IS_BROADWELL(dev))
> +		intel_disable_gt_powersave(dev);
>  
>  	simulated = dev_priv->gpu_error.stop_rings != 0;
>  
> @@ -733,7 +735,7 @@ 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) {
> +		if (INTEL_INFO(dev)->gen > 5 && !IS_BROADWELL(dev)) {
>  			mutex_lock(&dev->struct_mutex);
>  			intel_enable_gt_powersave(dev);
>  			mutex_unlock(&dev->struct_mutex);
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 3618bb0..25a97a6 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2420,6 +2420,7 @@ void i915_gem_reset(struct drm_device *dev)
>  void
>  i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
>  {
> +	struct drm_i915_private *dev_priv = ring->dev->dev_private;
>  	uint32_t seqno;
>  
>  	if (list_empty(&ring->request_list))
> @@ -2443,6 +2444,15 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
>  		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
>  			break;
>  
> +		/* Wa: can't find the w/a name.
> +		 * This doesn't actually implement the w/a, but it a workaround
> +		 * for the workaround. It defers using rc6 until we know valid
> +		 * state exists.
> +		 */
> +		if (IS_BROADWELL(ring->dev) && intel_enable_rc6(ring->dev) &&
> +		    !dev_priv->rps.enabled && ring->id == RCS)
> +			intel_enable_gt_powersave(ring->dev);

Nope, we won't rely on userspace submitting a command to enable a power
saving feature. There's a good chance that userspace won't submitting
anything, but still wake up from suspend, e.g. for background mail
checking. Especially on Android where opportunistic is used to
aggressively conserve battery power.

If just a MI_SET_CONTEXT isn't good enough and we need to save a valid 3d
context then we need to (shock, horror) emit the relevant minimal set of
3d state commands in the kernel before enabling rc6.

Aside: Series looks good otherwise, so I'll happily merge once it's
reviewed. No opinion on the RP* bikeshed (besides that your new names for
dev_priv->rps.foo are definitely clearer) as long as the connection
between the sane names and the Bspec names is documented somewhere.
-Daniel

> +
>  		i915_gem_object_move_to_inactive(obj);
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index f19e6ea..72c8e1d 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -10983,6 +10983,11 @@ void intel_modeset_init_hw(struct drm_device *dev)
>  
>  	intel_reset_dpio(dev);
>  
> +	if (IS_BROADWELL(dev)) {
> +		DRM_DEBUG_DRIVER("Deferring RC6 enabling until first batch is complete\n");
> +		return;
> +	}
> +
>  	mutex_lock(&dev->struct_mutex);
>  	intel_enable_gt_powersave(dev);
>  	mutex_unlock(&dev->struct_mutex);
> -- 
> 1.9.0
> 
> _______________________________________________
> 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] 97+ messages in thread

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-02-22 13:37       ` [PATCH 03/11] " Chris Wilson
  2014-02-22 19:34         ` Ben Widawsky
@ 2014-03-19  1:27         ` Ben Widawsky
  2014-03-19  2:38           ` Ben Widawsky
  1 sibling, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-19  1:27 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Intel GFX

On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > The names of the struct members for RPS are stupid. Every time I need to
> > do anything in this code I have to spend a significant amount of time to
> > remember what it all means. By renaming the variables (and adding the
> > comments) I hope to clear up the situation. Indeed doing this make some
> > upcoming patches more readable.
> > 
> > I've avoided ILK because it's possible that the naming used for Ironlake
> > matches what is in the docs. I believe the ILK power docs were never
> > published, and I am too lazy to dig them up.
> > 
> > While there may be mistakes, this patch was mostly done via sed. The
> > renaming of "hw_max" required a bit of interactivity.
> 
> It lost the distinction between RPe and RPn. I am in favour of keeping
> RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> soft values used for actual interaction.
> -Chris
> 

Okay, as stated before, you are correct - I need to bring back RPe/RPn
distinction. I think using the mix of values (basically s/_delay/_freq)
doesn't fully relize what I was hoping to achieve. I don't think there
is ever a case, except when debugging where it's easier to refer to the
RP mnemonic. How strongly do you feel about this one? I'd really prefer
to just fix RPe/RPn.

Does anyone else have an opinion on:
"max_freq_hardlimit" vs. "rp0"

Does anyone else want to review this one?

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

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-03-19  1:27         ` Ben Widawsky
@ 2014-03-19  2:38           ` Ben Widawsky
  2014-03-19  6:49             ` Chris Wilson
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-19  2:38 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Intel GFX

On Tue, Mar 18, 2014 at 06:27:03PM -0700, Ben Widawsky wrote:
> On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> > On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > > The names of the struct members for RPS are stupid. Every time I need to
> > > do anything in this code I have to spend a significant amount of time to
> > > remember what it all means. By renaming the variables (and adding the
> > > comments) I hope to clear up the situation. Indeed doing this make some
> > > upcoming patches more readable.
> > > 
> > > I've avoided ILK because it's possible that the naming used for Ironlake
> > > matches what is in the docs. I believe the ILK power docs were never
> > > published, and I am too lazy to dig them up.
> > > 
> > > While there may be mistakes, this patch was mostly done via sed. The
> > > renaming of "hw_max" required a bit of interactivity.
> > 
> > It lost the distinction between RPe and RPn. I am in favour of keeping
> > RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> > soft values used for actual interaction.
> > -Chris
> > 
> 
> Okay, as stated before, you are correct - I need to bring back RPe/RPn
> distinction. I think using the mix of values (basically s/_delay/_freq)
> doesn't fully relize what I was hoping to achieve. I don't think there
> is ever a case, except when debugging where it's easier to refer to the
> RP mnemonic. How strongly do you feel about this one? I'd really prefer
> to just fix RPe/RPn.
> 
> Does anyone else have an opinion on:
> "max_freq_hardlimit" vs. "rp0"
> 
> Does anyone else want to review this one?
> 

Okay, I started on this, and I somewhat agree. How about:

        u8 cur_freq;            /* Current frequency (cached, may not == HW) */
        u8 min_freq_softlimit;  /* Minimum frequency permitted by the driver */
        u8 max_freq_softlimit;  /* Max frequency permitted by the driver */
        u8 max_freq;            /* Maximum frequency, RP0 if not overclocking */
        u8 min_freq;            /* AKA RPn. Minimum frequency */
        u8 efficient_freq;      /* AKA RPe. Pre-determined balanced frequency */
        u8 rp1_freq;            /* "less than" RP0 power/freqency */
        u8 rp0_freq;            /* Non-overclocked max frequency. */

Conveniently, this matches sysfs, minus the efficiency one, and I don't think
there's a point in explicitly storing RPn, since it's always == min_freq.

> > -- 
> > Chris Wilson, Intel Open Source Technology Centre
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Ben Widawsky, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff*
  2014-03-19  2:38           ` Ben Widawsky
@ 2014-03-19  6:49             ` Chris Wilson
  0 siblings, 0 replies; 97+ messages in thread
From: Chris Wilson @ 2014-03-19  6:49 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX, Ben Widawsky

On Tue, Mar 18, 2014 at 07:38:43PM -0700, Ben Widawsky wrote:
> On Tue, Mar 18, 2014 at 06:27:03PM -0700, Ben Widawsky wrote:
> > On Sat, Feb 22, 2014 at 01:37:16PM +0000, Chris Wilson wrote:
> > > On Mon, Feb 17, 2014 at 07:01:44PM -0800, Ben Widawsky wrote:
> > > > The names of the struct members for RPS are stupid. Every time I need to
> > > > do anything in this code I have to spend a significant amount of time to
> > > > remember what it all means. By renaming the variables (and adding the
> > > > comments) I hope to clear up the situation. Indeed doing this make some
> > > > upcoming patches more readable.
> > > > 
> > > > I've avoided ILK because it's possible that the naming used for Ironlake
> > > > matches what is in the docs. I believe the ILK power docs were never
> > > > published, and I am too lazy to dig them up.
> > > > 
> > > > While there may be mistakes, this patch was mostly done via sed. The
> > > > renaming of "hw_max" required a bit of interactivity.
> > > 
> > > It lost the distinction between RPe and RPn. I am in favour of keeping
> > > RP0, RP1, RPe, RPn for the hardware/spec values and adding the set of
> > > soft values used for actual interaction.
> > > -Chris
> > > 
> > 
> > Okay, as stated before, you are correct - I need to bring back RPe/RPn
> > distinction. I think using the mix of values (basically s/_delay/_freq)
> > doesn't fully relize what I was hoping to achieve. I don't think there
> > is ever a case, except when debugging where it's easier to refer to the
> > RP mnemonic. How strongly do you feel about this one? I'd really prefer
> > to just fix RPe/RPn.
> > 
> > Does anyone else have an opinion on:
> > "max_freq_hardlimit" vs. "rp0"
> > 
> > Does anyone else want to review this one?
> > 
> 
> Okay, I started on this, and I somewhat agree. How about:
> 
>         u8 cur_freq;            /* Current frequency (cached, may not == HW) */
>         u8 min_freq_softlimit;  /* Minimum frequency permitted by the driver */
>         u8 max_freq_softlimit;  /* Max frequency permitted by the driver */
>         u8 max_freq;            /* Maximum frequency, RP0 if not overclocking */
>         u8 min_freq;            /* AKA RPn. Minimum frequency */
>         u8 efficient_freq;      /* AKA RPe. Pre-determined balanced frequency */
>         u8 rp1_freq;            /* "less than" RP0 power/freqency */
>         u8 rp0_freq;            /* Non-overclocked max frequency. */

Yes. If we include a couple of comments where we read from the cap
register to reference the spec names, I like it a lot.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 11/11] [v4] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-03-04 14:30             ` Daniel Vetter
@ 2014-03-20  0:41               ` Ben Widawsky
  2014-03-20 13:42                 ` Daniel Vetter
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  0:41 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David E. Box, Intel GFX, Kristen Carlson Accardi, Ben Widawsky

On Tue, Mar 04, 2014 at 03:30:14PM +0100, Daniel Vetter wrote:
> On Wed, Feb 19, 2014 at 10:27:20PM -0800, Ben Widawsky wrote:
> > RC6 works a lot like HW contexts in that when the GPU enters RC6 it
> > saves away the state to a context, and loads it upon wake.
> > 
> > It's to be somewhat expected that BIOS will not set up valid GPU state.
> > As a result, if loading bad state can cause the GPU to get angry, it
> > would make sense then that we need to load state first. There are two
> > ways in which we can do this:
> > 
> > 1. Create 3d state in the driver, load it up, then enable RC6.
> > 1b. Reuse a known good state, [and if needed,] just bind objects where
> > needed. Then enable RC6.
> > 2. Hold off enabling RC6 until userspace has had a chance to complete
> > batches.
> > 
> > There has been discussions in the past with #1 as it has been
> > recommended for fixes elsewhere. I'm not opposed to it, I'd just like to
> > do the easy thing now to enable the platform.
> > 
> > This patch is a hack that implement option #2. It will defer enabling
> > rc6 until the first batch from userspace has been retired. It suffers
> > two flaws. The first is, if the driver is loaded, but a batch is not
> > submitted/completed, we'll never enter rc6. The other is, it expects
> > userspace to submit a batch with 3d state first. Both of these things
> > are not actual flaws for most users because most users will boot to a
> > graphical composited desktop. Both mesa, and X will always emit the
> > necessary 3d state.
> > 
> > Once a context is loaded and we enable rc6, the default context should
> > inherit the proper state because we always inhibit the restore for the
> > default context. This assumes certain things about the workaround/issue
> > itself to which I am not privy (primarily that the indirect state
> > objects don't actually need to exist).
> > 
> > With that, there are currently 4 options for BDW:
> > 1. Don't use RC6.
> > 2. Use RC6 and expect a hang on the first batch submitted for every
> > context.
> > 3. Use RC6 and use this patch.
> > 4. Wait for another workaround implementation.
> > 
> > NOTE: This patch could be used against other platforms as well.
> > 
> > v2: Re-add accidentally dropped hunk (Ben)
> > 
> > v3: Now more compilable (Ben)
> > 
> > v4: Use the existing enable flag for rc6. This will also make the
> > suspend/resume case work properly, which is broken in v3.
> > Disable rc6 on reset, and defer re-enabling until the first batch.
> > 
> > The fact that RC6 residency continues to increment, and that this patch
> > prevents a hang on BDW silicon has been:
> > Tested-by: Kenneth Graunke <kenneth@whitecape.org> (v1)
> > 
> > Cc: David E. Box <david.e.box@intel.com>
> > Cc: Kristen Carlson Accardi <kristen@linux.intel.com>
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > 
> > squash! drm/i915/bdw: Ensure a context is loaded before RC6
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c      |  4 +++-
> >  drivers/gpu/drm/i915/i915_gem.c      | 10 ++++++++++
> >  drivers/gpu/drm/i915/intel_display.c |  5 +++++
> >  3 files changed, 18 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 2d05d7c..7fdfc0e 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -679,6 +679,8 @@ int i915_reset(struct drm_device *dev)
> >  	mutex_lock(&dev->struct_mutex);
> >  
> >  	i915_gem_reset(dev);
> > +	if (IS_BROADWELL(dev))
> > +		intel_disable_gt_powersave(dev);
> >  
> >  	simulated = dev_priv->gpu_error.stop_rings != 0;
> >  
> > @@ -733,7 +735,7 @@ 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) {
> > +		if (INTEL_INFO(dev)->gen > 5 && !IS_BROADWELL(dev)) {
> >  			mutex_lock(&dev->struct_mutex);
> >  			intel_enable_gt_powersave(dev);
> >  			mutex_unlock(&dev->struct_mutex);
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> > index 3618bb0..25a97a6 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -2420,6 +2420,7 @@ void i915_gem_reset(struct drm_device *dev)
> >  void
> >  i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
> >  {
> > +	struct drm_i915_private *dev_priv = ring->dev->dev_private;
> >  	uint32_t seqno;
> >  
> >  	if (list_empty(&ring->request_list))
> > @@ -2443,6 +2444,15 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
> >  		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
> >  			break;
> >  
> > +		/* Wa: can't find the w/a name.
> > +		 * This doesn't actually implement the w/a, but it a workaround
> > +		 * for the workaround. It defers using rc6 until we know valid
> > +		 * state exists.
> > +		 */
> > +		if (IS_BROADWELL(ring->dev) && intel_enable_rc6(ring->dev) &&
> > +		    !dev_priv->rps.enabled && ring->id == RCS)
> > +			intel_enable_gt_powersave(ring->dev);
> 
> Nope, we won't rely on userspace submitting a command to enable a power
> saving feature. There's a good chance that userspace won't submitting
> anything, but still wake up from suspend, e.g. for background mail
> checking. Especially on Android where opportunistic is used to
> aggressively conserve battery power.

Your suspend example with mail is also not great. So the thing wakes up
for a second to check mail, and GPU is not in RC6, then goes back to
sleep. Big deal. If a user sees a new mail and uses the mail app, she
will get RC6. Essentially on any composited windowing system, that the
user is actively interfacing with, you get RC6 (and deeper states).

> 
> If just a MI_SET_CONTEXT isn't good enough and we need to save a valid 3d
> context then we need to (shock, horror) emit the relevant minimal set of
> 3d state commands in the kernel before enabling rc6.
> 
> Aside: Series looks good otherwise, so I'll happily merge once it's
> reviewed. No opinion on the RP* bikeshed (besides that your new names for
> dev_priv->rps.foo are definitely clearer) as long as the connection
> between the sane names and the Bspec names is documented somewhere.
> -Daniel
> 

I can't say it's completely unexpected that this would be your response,
but I do feel like you've ignored my argument that this is better than
the current situation. Not merging this patch only keeps things bad.

So I'd like you to re-consider merging this patch instead of waiting for
the perfect solution. This patch requires a lot less review than the
real fix. It has been tested by several people (I can ask them to put
their reviewed by on it). It enables rc6 for people today, and this
includes pc7, and deeper package and C states. It's very easy to revert
if/when we get a real fix. Real users benefit from this patch. Real
users are not hurt by this patch because if userspace is submitting bad
state setup, they'll have the same or worse experience than failing RC6.

As an aside, this needs to come before I enable rc6 anyway. So the order
way bad.

> > +
> >  		i915_gem_object_move_to_inactive(obj);
> >  	}
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index f19e6ea..72c8e1d 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -10983,6 +10983,11 @@ void intel_modeset_init_hw(struct drm_device *dev)
> >  
> >  	intel_reset_dpio(dev);
> >  
> > +	if (IS_BROADWELL(dev)) {
> > +		DRM_DEBUG_DRIVER("Deferring RC6 enabling until first batch is complete\n");
> > +		return;
> > +	}
> > +
> >  	mutex_lock(&dev->struct_mutex);
> >  	intel_enable_gt_powersave(dev);
> >  	mutex_unlock(&dev->struct_mutex);
> > -- 
> > 1.9.0
> > 
> > _______________________________________________
> > 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

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets
  2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
                       ` (10 preceding siblings ...)
  2014-02-18  3:01     ` [PATCH 11/11] drm/i915/bdw: Ensure a context is loaded before RC6 Ben Widawsky
@ 2014-03-20  1:31     ` Ben Widawsky
  2014-03-20  1:31       ` [PATCH 01/12] drm/i915: Reorganize the overclock code Ben Widawsky
                         ` (11 more replies)
  11 siblings, 12 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX


Ben Widawsky (12):
  drm/i915: Reorganize the overclock code
  drm/i915: Fix coding style for RPS
  drm/i915: Store the HW min frequency as min_freq
  drm/i915: Rename and comment all the RPS *stuff*
  drm/i915: Remove extraneous MMIO for RPS
  drm/i915: remove rps local variables
  drm/i915/bdw: Set initial rps freq to RP0
  drm/i915/bdw: Extract rp_state_caps logic
  drm/i915/bdw: RPS frequency bits are the same as HSW
  drm/i915/bdw: Implement a basic PM interrupt handler
  drm/i915/bdw: Ensure a context is loaded before RC6
  drm/i915/bdw: Enable RC6

 drivers/gpu/drm/i915/i915_debugfs.c  |  26 ++---
 drivers/gpu/drm/i915/i915_drv.c      |   4 +-
 drivers/gpu/drm/i915/i915_drv.h      |  25 ++--
 drivers/gpu/drm/i915/i915_gem.c      |  10 ++
 drivers/gpu/drm/i915/i915_irq.c      | 109 +++++++++++++++---
 drivers/gpu/drm/i915/i915_reg.h      |   1 +
 drivers/gpu/drm/i915/i915_sysfs.c    |  81 ++++++-------
 drivers/gpu/drm/i915/intel_display.c |   5 +
 drivers/gpu/drm/i915/intel_drv.h     |   2 +
 drivers/gpu/drm/i915/intel_pm.c      | 213 +++++++++++++++++++++--------------
 10 files changed, 306 insertions(+), 170 deletions(-)

-- 
1.9.0

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

* [PATCH 01/12] drm/i915: Reorganize the overclock code
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:23         ` Chris Wilson
  2014-03-20  1:31       ` [PATCH 02/12] drm/i915: Fix coding style for RPS Ben Widawsky
                         ` (10 subsequent siblings)
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

The existing code (which I changed last) was very convoluted. I believe
it was attempting to skip the overclock portion if the previous pcode
write failed. When I last touched the code, I was preserving this
behavior. There is some benefit to doing it that way in that if the
first pcode access fails, the later is likely invalid.

Having a bit more confidence in my understanding of how things work, I
now feel it's better to have clear, readable, code than to try to skip
over this one operation in an unusual case.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 39f3238..dd3a121 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3326,7 +3326,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	struct intel_ring_buffer *ring;
 	u32 rp_state_cap, hw_max, hw_min;
 	u32 gt_perf_status;
-	u32 rc6vids, pcu_mbox, rc6_mask = 0;
+	u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
 	u32 gtfifodbg;
 	int rc6_mode;
 	int i, ret;
@@ -3414,17 +3414,15 @@ static void gen6_enable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
 
 	ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0);
-	if (!ret) {
-		pcu_mbox = 0;
-		ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
-		if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
-			DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
-					 (dev_priv->rps.max_delay & 0xff) * 50,
-					 (pcu_mbox & 0xff) * 50);
-			dev_priv->rps.hw_max = pcu_mbox & 0xff;
-		}
-	} else {
+	if (ret)
 		DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
+
+	ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
+	if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
+		DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
+				 (dev_priv->rps.max_delay & 0xff) * 50,
+				 (pcu_mbox & 0xff) * 50);
+		dev_priv->rps.hw_max = pcu_mbox & 0xff;
 	}
 
 	dev_priv->rps.power = HIGH_POWER; /* force a reset */
-- 
1.9.0

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

* [PATCH 02/12] drm/i915: Fix coding style for RPS
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
  2014-03-20  1:31       ` [PATCH 01/12] drm/i915: Reorganize the overclock code Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:31         ` Chris Wilson
  2014-03-24 10:30         ` Deepak S
  2014-03-20  1:31       ` [PATCH 03/12] drm/i915: Store the HW min frequency as min_freq Ben Widawsky
                         ` (9 subsequent siblings)
  11 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

Introduced:
commit b8a5ff8d7c676a04e0da5ec16bb068dd39459042
Author: Jeff McGee <jeff.mcgee@intel.com>
Date:   Tue Feb 4 11:37:01 2014 -0600

    drm/i915: Update rps interrupt limits

Cc: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_sysfs.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 0c741f4..e9ffefb 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -356,12 +356,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 			valleyview_set_rps(dev, val);
 		else
 			gen6_set_rps(dev, val);
-	}
-	else if (!IS_VALLEYVIEW(dev))
-		/* We still need gen6_set_rps to process the new max_delay
-		   and update the interrupt limits even though frequency
-		   request is unchanged. */
+	} else if (!IS_VALLEYVIEW(dev)) {
+		/* We still need gen6_set_rps to process the new max_delay and
+		 * update the interrupt limits even though frequency request is
+		 * unchanged. */
 		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
@@ -430,12 +430,12 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 			valleyview_set_rps(dev, val);
 		else
 			gen6_set_rps(dev, val);
-	}
-	else if (!IS_VALLEYVIEW(dev))
-		/* We still need gen6_set_rps to process the new min_delay
-		   and update the interrupt limits even though frequency
-		   request is unchanged. */
+	} else if (!IS_VALLEYVIEW(dev)) {
+		/* We still need gen6_set_rps to process the new min_delay and
+		 * update the interrupt limits even though frequency request is
+		 * unchanged. */
 		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-- 
1.9.0

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

* [PATCH 03/12] drm/i915: Store the HW min frequency as min_freq
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
  2014-03-20  1:31       ` [PATCH 01/12] drm/i915: Reorganize the overclock code Ben Widawsky
  2014-03-20  1:31       ` [PATCH 02/12] drm/i915: Fix coding style for RPS Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:29         ` Chris Wilson
  2014-03-24 10:31         ` Deepak S
  2014-03-20  1:31       ` [PATCH 04/12] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
                         ` (8 subsequent siblings)
  11 siblings, 2 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

this leaves a temporarily awkward min_delay (the soft limit) with the
new min_freq (the hardware limit). It's fixed in the next patch.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_drv.h | 1 +
 drivers/gpu/drm/i915/intel_pm.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9cd870f..241f5e1 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -987,6 +987,7 @@ struct intel_gen6_power_mgmt {
 	u8 rp1_delay;
 	u8 rp0_delay;
 	u8 hw_max;
+	u8 min_freq;
 
 	bool rp_up_masked;
 	bool rp_down_masked;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index dd3a121..dd631d1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3354,7 +3354,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 
 	/* In units of 50MHz */
 	dev_priv->rps.hw_max = hw_max = rp_state_cap & 0xff;
-	hw_min = (rp_state_cap >> 16) & 0xff;
+	dev_priv->rps.min_freq = hw_min = (rp_state_cap >> 16) & 0xff;
 	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
 	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
 	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
-- 
1.9.0

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

* [PATCH 04/12] drm/i915: Rename and comment all the RPS *stuff*
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (2 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 03/12] drm/i915: Store the HW min frequency as min_freq Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:01         ` Chris Wilson
  2014-03-20  1:31       ` [PATCH 05/12] drm/i915: Remove extraneous MMIO for RPS Ben Widawsky
                         ` (7 subsequent siblings)
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

The names of the struct members for RPS are stupid. Every time I need to
do anything in this code I have to spend a significant amount of time to
remember what it all means. By renaming the variables (and adding the
comments) I hope to clear up the situation. Indeed doing this make some
upcoming patches more readable.

I've avoided ILK because it's possible that the naming used for Ironlake
matches what is in the docs. I believe the ILK power docs were never
published, and I am too lazy to dig them up.

v2: leave rp0, and rp1 in the names. It is useful to have these limits
available at times. min_freq and max_freq (which may be equal to rp0, or
rp1 depending on the platform) represent the actual HW min and max.

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  26 ++++----
 drivers/gpu/drm/i915/i915_drv.h     |  26 +++++---
 drivers/gpu/drm/i915/i915_irq.c     |  25 ++++----
 drivers/gpu/drm/i915/i915_sysfs.c   |  32 +++++-----
 drivers/gpu/drm/i915/intel_pm.c     | 118 ++++++++++++++++++------------------
 5 files changed, 120 insertions(+), 107 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 6037913..d1e0a36 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1026,7 +1026,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 			   max_freq * GT_FREQUENCY_MULTIPLIER);
 
 		seq_printf(m, "Max overclocked frequency: %dMHz\n",
-			   dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER);
+			   dev_priv->rps.max_freq * GT_FREQUENCY_MULTIPLIER);
 	} else if (IS_VALLEYVIEW(dev)) {
 		u32 freq_sts, val;
 
@@ -1498,8 +1498,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 
 	seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
-	for (gpu_freq = dev_priv->rps.min_delay;
-	     gpu_freq <= dev_priv->rps.max_delay;
+	for (gpu_freq = dev_priv->rps.min_freq_softlimit;
+	     gpu_freq <= dev_priv->rps.max_freq_softlimit;
 	     gpu_freq++) {
 		ia_freq = gpu_freq;
 		sandybridge_pcode_read(dev_priv,
@@ -3449,9 +3449,9 @@ i915_max_freq_get(void *data, u64 *val)
 		return ret;
 
 	if (IS_VALLEYVIEW(dev))
-		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
+		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit);
 	else
-		*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
+		*val = dev_priv->rps.max_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -3488,16 +3488,16 @@ i915_max_freq_set(void *data, u64 val)
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq;
 		hw_min = (rp_state_cap >> 16) & 0xff;
 	}
 
-	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
+	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.max_delay = val;
+	dev_priv->rps.max_freq_softlimit = val;
 
 	if (IS_VALLEYVIEW(dev))
 		valleyview_set_rps(dev, val);
@@ -3530,9 +3530,9 @@ i915_min_freq_get(void *data, u64 *val)
 		return ret;
 
 	if (IS_VALLEYVIEW(dev))
-		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
+		*val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit);
 	else
-		*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
+		*val = dev_priv->rps.min_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -3569,16 +3569,16 @@ i915_min_freq_set(void *data, u64 val)
 		do_div(val, GT_FREQUENCY_MULTIPLIER);
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq;
 		hw_min = (rp_state_cap >> 16) & 0xff;
 	}
 
-	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
+	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.min_delay = val;
+	dev_priv->rps.min_freq_softlimit = val;
 
 	if (IS_VALLEYVIEW(dev))
 		valleyview_set_rps(dev, val);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 241f5e1..c5c5760 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -980,14 +980,24 @@ struct intel_gen6_power_mgmt {
 	struct work_struct work;
 	u32 pm_iir;
 
-	u8 cur_delay;
-	u8 min_delay;
-	u8 max_delay;
-	u8 rpe_delay;
-	u8 rp1_delay;
-	u8 rp0_delay;
-	u8 hw_max;
-	u8 min_freq;
+	/* Frequencies are stored in potentially platform dependent multiples.
+	 * In other words, *_freq needs to be multiplied by X to be interesting.
+	 * Soft limits are those which are used for the dynamic reclocking done
+	 * by the driver (raise frequencies under heavy loads, and lower for
+	 * lighter loads). Hard limits are those imposed by the hardware.
+	 *
+	 * A distinction is made for overclocking, which is never enabled by
+	 * default, and is considered to be above the hard limit if it's
+	 * possible at all.
+	 */
+	u8 cur_freq;		/* Current frequency (cached, may not == HW) */
+	u8 min_freq_softlimit;	/* Minimum frequency permitted by the driver */
+	u8 max_freq_softlimit;	/* Max frequency permitted by the driver */
+	u8 max_freq;		/* Maximum frequency, RP0 if not overclocking */
+	u8 min_freq;		/* AKA RPn. Minimum frequency */
+	u8 efficient_freq;	/* AKA RPe. Pre-determined balanced frequency */
+	u8 rp1_freq;		/* "less than" RP0 power/freqency */
+	u8 rp0_freq;		/* Non-overclocked max frequency. */
 
 	bool rp_up_masked;
 	bool rp_down_masked;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 888f08c..4b4aeb3 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1088,7 +1088,7 @@ void gen6_set_pm_mask(struct drm_i915_private *dev_priv,
 			     u32 pm_iir, int new_delay)
 {
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
-		if (new_delay >= dev_priv->rps.max_delay) {
+		if (new_delay >= dev_priv->rps.max_freq_softlimit) {
 			/* Mask UP THRESHOLD Interrupts */
 			I915_WRITE(GEN6_PMINTRMSK,
 				   I915_READ(GEN6_PMINTRMSK) |
@@ -1103,7 +1103,7 @@ void gen6_set_pm_mask(struct drm_i915_private *dev_priv,
 			dev_priv->rps.rp_down_masked = false;
 		}
 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
-		if (new_delay <= dev_priv->rps.min_delay) {
+		if (new_delay <= dev_priv->rps.min_freq_softlimit) {
 			/* Mask DOWN THRESHOLD Interrupts */
 			I915_WRITE(GEN6_PMINTRMSK,
 				   I915_READ(GEN6_PMINTRMSK) |
@@ -1149,38 +1149,39 @@ static void gen6_pm_rps_work(struct work_struct *work)
 			adj *= 2;
 		else
 			adj = 1;
-		new_delay = dev_priv->rps.cur_delay + adj;
+		new_delay = dev_priv->rps.cur_freq + adj;
 
 		/*
 		 * For better performance, jump directly
 		 * to RPe if we're below it.
 		 */
-		if (new_delay < dev_priv->rps.rpe_delay)
-			new_delay = dev_priv->rps.rpe_delay;
+		if (new_delay < dev_priv->rps.efficient_freq)
+			new_delay = dev_priv->rps.efficient_freq;
 	} else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) {
-		if (dev_priv->rps.cur_delay > dev_priv->rps.rpe_delay)
-			new_delay = dev_priv->rps.rpe_delay;
+		if (dev_priv->rps.cur_freq > dev_priv->rps.efficient_freq)
+			new_delay = dev_priv->rps.efficient_freq;
 		else
-			new_delay = dev_priv->rps.min_delay;
+			new_delay = dev_priv->rps.min_freq_softlimit;
 		adj = 0;
 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
 		if (adj < 0)
 			adj *= 2;
 		else
 			adj = -1;
-		new_delay = dev_priv->rps.cur_delay + adj;
+		new_delay = dev_priv->rps.cur_freq + adj;
 	} else { /* unknown event */
-		new_delay = dev_priv->rps.cur_delay;
+		new_delay = dev_priv->rps.cur_freq;
 	}
 
 	/* sysfs frequency interfaces may have snuck in while servicing the
 	 * interrupt
 	 */
 	new_delay = clamp_t(int, new_delay,
-			    dev_priv->rps.min_delay, dev_priv->rps.max_delay);
+			    dev_priv->rps.min_freq_softlimit,
+			    dev_priv->rps.max_freq_softlimit);
 
 	gen6_set_pm_mask(dev_priv, pm_iir, new_delay);
-	dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
+	dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_freq;
 
 	if (IS_VALLEYVIEW(dev_priv->dev))
 		valleyview_set_rps(dev_priv->dev, new_delay);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e9ffefb..e3fa8cd 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -269,7 +269,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 		freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
 		ret = vlv_gpu_freq(dev_priv, (freq >> 8) & 0xff);
 	} else {
-		ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.cur_freq * GT_FREQUENCY_MULTIPLIER;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
@@ -284,7 +284,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-			vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay));
+			vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
 }
 
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -298,9 +298,9 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (IS_VALLEYVIEW(dev_priv->dev))
-		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
+		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit);
 	else
-		ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.max_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -334,13 +334,13 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		val /= GT_FREQUENCY_MULTIPLIER;
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq;
 		non_oc_max = (rp_state_cap & 0xff);
 		hw_min = ((rp_state_cap & 0xff0000) >> 16);
 	}
 
 	if (val < hw_min || val > hw_max ||
-	    val < dev_priv->rps.min_delay) {
+	    val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
@@ -349,9 +349,9 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		DRM_DEBUG("User requested overclocking to %d\n",
 			  val * GT_FREQUENCY_MULTIPLIER);
 
-	dev_priv->rps.max_delay = val;
+	dev_priv->rps.max_freq_softlimit = val;
 
-	if (dev_priv->rps.cur_delay > val) {
+	if (dev_priv->rps.cur_freq > val) {
 		if (IS_VALLEYVIEW(dev))
 			valleyview_set_rps(dev, val);
 		else
@@ -360,7 +360,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		/* We still need gen6_set_rps to process the new max_delay and
 		 * update the interrupt limits even though frequency request is
 		 * unchanged. */
-		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+		gen6_set_rps(dev, dev_priv->rps.cur_freq);
 	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -379,9 +379,9 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (IS_VALLEYVIEW(dev_priv->dev))
-		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
+		ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit);
 	else
-		ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
+		ret = dev_priv->rps.min_freq_softlimit * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -414,18 +414,18 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 		val /= GT_FREQUENCY_MULTIPLIER;
 
 		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-		hw_max = dev_priv->rps.hw_max;
+		hw_max = dev_priv->rps.max_freq;
 		hw_min = ((rp_state_cap & 0xff0000) >> 16);
 	}
 
-	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
+	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	dev_priv->rps.min_delay = val;
+	dev_priv->rps.min_freq_softlimit = val;
 
-	if (dev_priv->rps.cur_delay < val) {
+	if (dev_priv->rps.cur_freq < val) {
 		if (IS_VALLEYVIEW(dev))
 			valleyview_set_rps(dev, val);
 		else
@@ -434,7 +434,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 		/* We still need gen6_set_rps to process the new min_delay and
 		 * update the interrupt limits even though frequency request is
 		 * unchanged. */
-		gen6_set_rps(dev, dev_priv->rps.cur_delay);
+		gen6_set_rps(dev, dev_priv->rps.cur_freq);
 	}
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index dd631d1..3db7c40 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2907,9 +2907,9 @@ static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 val)
 	 * the hw runs at the minimal clock before selecting the desired
 	 * frequency, if the down threshold expires in that window we will not
 	 * receive a down interrupt. */
-	limits = dev_priv->rps.max_delay << 24;
-	if (val <= dev_priv->rps.min_delay)
-		limits |= dev_priv->rps.min_delay << 16;
+	limits = dev_priv->rps.max_freq_softlimit << 24;
+	if (val <= dev_priv->rps.min_freq_softlimit)
+		limits |= dev_priv->rps.min_freq_softlimit << 16;
 
 	return limits;
 }
@@ -2921,26 +2921,26 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 	new_power = dev_priv->rps.power;
 	switch (dev_priv->rps.power) {
 	case LOW_POWER:
-		if (val > dev_priv->rps.rpe_delay + 1 && val > dev_priv->rps.cur_delay)
+		if (val > dev_priv->rps.efficient_freq + 1 && val > dev_priv->rps.cur_freq)
 			new_power = BETWEEN;
 		break;
 
 	case BETWEEN:
-		if (val <= dev_priv->rps.rpe_delay && val < dev_priv->rps.cur_delay)
+		if (val <= dev_priv->rps.efficient_freq && val < dev_priv->rps.cur_freq)
 			new_power = LOW_POWER;
-		else if (val >= dev_priv->rps.rp0_delay && val > dev_priv->rps.cur_delay)
+		else if (val >= dev_priv->rps.rp0_freq && val > dev_priv->rps.cur_freq)
 			new_power = HIGH_POWER;
 		break;
 
 	case HIGH_POWER:
-		if (val < (dev_priv->rps.rp1_delay + dev_priv->rps.rp0_delay) >> 1 && val < dev_priv->rps.cur_delay)
+		if (val < (dev_priv->rps.rp1_freq + dev_priv->rps.rp0_freq) >> 1 && val < dev_priv->rps.cur_freq)
 			new_power = BETWEEN;
 		break;
 	}
 	/* Max/min bins are special */
-	if (val == dev_priv->rps.min_delay)
+	if (val == dev_priv->rps.min_freq_softlimit)
 		new_power = LOW_POWER;
-	if (val == dev_priv->rps.max_delay)
+	if (val == dev_priv->rps.max_freq_softlimit)
 		new_power = HIGH_POWER;
 	if (new_power == dev_priv->rps.power)
 		return;
@@ -3014,10 +3014,10 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-	WARN_ON(val > dev_priv->rps.max_delay);
-	WARN_ON(val < dev_priv->rps.min_delay);
+	WARN_ON(val > dev_priv->rps.max_freq_softlimit);
+	WARN_ON(val < dev_priv->rps.min_freq_softlimit);
 
-	if (val == dev_priv->rps.cur_delay) {
+	if (val == dev_priv->rps.cur_freq) {
 		/* min/max delay may still have been modified so be sure to
 		 * write the limits value */
 		I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
@@ -3045,7 +3045,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 
 	POSTING_READ(GEN6_RPNSWREQ);
 
-	dev_priv->rps.cur_delay = val;
+	dev_priv->rps.cur_freq = val;
 
 	trace_intel_gpu_freq_change(val * 50);
 }
@@ -3065,7 +3065,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 	 * When we are idle.  Drop to min voltage state.
 	 */
 
-	if (dev_priv->rps.cur_delay <= dev_priv->rps.min_delay)
+	if (dev_priv->rps.cur_freq <= dev_priv->rps.min_freq_softlimit)
 		return;
 
 	/* Mask turbo interrupt so that they will not come in between */
@@ -3082,10 +3082,10 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 		return;
 	}
 
-	dev_priv->rps.cur_delay = dev_priv->rps.min_delay;
+	dev_priv->rps.cur_freq = dev_priv->rps.min_freq_softlimit;
 
 	vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ,
-					dev_priv->rps.min_delay);
+					dev_priv->rps.min_freq_softlimit);
 
 	if (wait_for(((vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS))
 				& GENFREQSTATUS) == 0, 5))
@@ -3099,7 +3099,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 	/* Unmask Up interrupts */
 	dev_priv->rps.rp_up_masked = true;
 	gen6_set_pm_mask(dev_priv, GEN6_PM_RP_DOWN_THRESHOLD,
-						dev_priv->rps.min_delay);
+						dev_priv->rps.min_freq_softlimit);
 }
 
 void gen6_rps_idle(struct drm_i915_private *dev_priv)
@@ -3111,7 +3111,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
 		if (IS_VALLEYVIEW(dev))
 			vlv_set_rps_idle(dev_priv);
 		else
-			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
+			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
 		dev_priv->rps.last_adj = 0;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -3124,9 +3124,9 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv)
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (dev_priv->rps.enabled) {
 		if (IS_VALLEYVIEW(dev))
-			valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
+			valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit);
 		else
-			gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
+			gen6_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit);
 		dev_priv->rps.last_adj = 0;
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
@@ -3137,20 +3137,20 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-	WARN_ON(val > dev_priv->rps.max_delay);
-	WARN_ON(val < dev_priv->rps.min_delay);
+	WARN_ON(val > dev_priv->rps.max_freq_softlimit);
+	WARN_ON(val < dev_priv->rps.min_freq_softlimit);
 
 	DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
-			 dev_priv->rps.cur_delay,
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
+			 dev_priv->rps.cur_freq,
 			 vlv_gpu_freq(dev_priv, val), val);
 
-	if (val == dev_priv->rps.cur_delay)
+	if (val == dev_priv->rps.cur_freq)
 		return;
 
 	vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val);
 
-	dev_priv->rps.cur_delay = val;
+	dev_priv->rps.cur_freq = val;
 
 	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
@@ -3292,8 +3292,8 @@ static void gen8_enable_rps(struct drm_device *dev)
 
 	/* Docs recommend 900MHz, and 300 MHz respectively */
 	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
-		   dev_priv->rps.max_delay << 24 |
-		   dev_priv->rps.min_delay << 16);
+		   dev_priv->rps.max_freq_softlimit << 24 |
+		   dev_priv->rps.min_freq_softlimit << 16);
 
 	I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */
 	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/
@@ -3352,20 +3352,22 @@ static void gen6_enable_rps(struct drm_device *dev)
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
-	/* In units of 50MHz */
-	dev_priv->rps.hw_max = hw_max = rp_state_cap & 0xff;
+	/* All of these values are in units of 50MHz */
+	dev_priv->rps.cur_freq = 0;
+	/* hw_max = RP0 until we check for overclocking */
+	dev_priv->rps.max_freq = hw_max = rp_state_cap & 0xff;
+	/* static values from HW: RP0 < RPe < RP1 < RPn (min_freq) */
+	dev_priv->rps.rp1_freq = (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.rp0_freq = (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq;
 	dev_priv->rps.min_freq = hw_min = (rp_state_cap >> 16) & 0xff;
-	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;
-	dev_priv->rps.cur_delay = 0;
 
 	/* Preserve min/max settings in case of re-init */
-	if (dev_priv->rps.max_delay == 0)
-		dev_priv->rps.max_delay = hw_max;
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = hw_max;
 
-	if (dev_priv->rps.min_delay == 0)
-		dev_priv->rps.min_delay = hw_min;
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = hw_min;
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -3420,13 +3422,13 @@ static void gen6_enable_rps(struct drm_device *dev)
 	ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
 	if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
 		DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
-				 (dev_priv->rps.max_delay & 0xff) * 50,
+				 (dev_priv->rps.max_freq_softlimit & 0xff) * 50,
 				 (pcu_mbox & 0xff) * 50);
-		dev_priv->rps.hw_max = pcu_mbox & 0xff;
+		dev_priv->rps.max_freq = pcu_mbox & 0xff;
 	}
 
 	dev_priv->rps.power = HIGH_POWER; /* force a reset */
-	gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
+	gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
 
 	gen6_enable_rps_interrupts(dev);
 
@@ -3482,9 +3484,9 @@ void gen6_update_ring_freq(struct drm_device *dev)
 	 * to use for memory access.  We do this by specifying the IA frequency
 	 * the PCU should use as a reference to determine the ring frequency.
 	 */
-	for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay;
+	for (gpu_freq = dev_priv->rps.max_freq_softlimit; gpu_freq >= dev_priv->rps.min_freq_softlimit;
 	     gpu_freq--) {
-		int diff = dev_priv->rps.max_delay - gpu_freq;
+		int diff = dev_priv->rps.max_freq_softlimit - gpu_freq;
 		unsigned int ia_freq = 0, ring_freq = 0;
 
 		if (INTEL_INFO(dev)->gen >= 8) {
@@ -3650,20 +3652,20 @@ static void valleyview_enable_rps(struct drm_device *dev)
 	DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
 	DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
 
-	dev_priv->rps.cur_delay = (val >> 8) & 0xff;
+	dev_priv->rps.cur_freq = (val >> 8) & 0xff;
 	DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
-			 dev_priv->rps.cur_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
+			 dev_priv->rps.cur_freq);
 
-	dev_priv->rps.hw_max = hw_max = valleyview_rps_max_freq(dev_priv);
+	dev_priv->rps.max_freq = hw_max = valleyview_rps_max_freq(dev_priv);
 	DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
 			 vlv_gpu_freq(dev_priv, hw_max),
 			 hw_max);
 
-	dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv);
+	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.rpe_delay),
-			 dev_priv->rps.rpe_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
+			 dev_priv->rps.efficient_freq);
 
 	hw_min = valleyview_rps_min_freq(dev_priv);
 	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
@@ -3671,17 +3673,17 @@ static void valleyview_enable_rps(struct drm_device *dev)
 			 hw_min);
 
 	/* Preserve min/max settings in case of re-init */
-	if (dev_priv->rps.max_delay == 0)
-		dev_priv->rps.max_delay = hw_max;
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = hw_max;
 
-	if (dev_priv->rps.min_delay == 0)
-		dev_priv->rps.min_delay = hw_min;
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = hw_min;
 
 	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
-			 dev_priv->rps.rpe_delay);
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
+			 dev_priv->rps.efficient_freq);
 
-	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
+	valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq);
 
 	dev_priv->rps.rp_up_masked = false;
 	dev_priv->rps.rp_down_masked = false;
@@ -4122,7 +4124,7 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
 
 	assert_spin_locked(&mchdev_lock);
 
-	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_delay * 4));
+	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_freq * 4));
 	pxvid = (pxvid >> 24) & 0x7f;
 	ext_v = pvid_to_extvid(dev_priv, pxvid);
 
-- 
1.9.0

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

* [PATCH 05/12] drm/i915: Remove extraneous MMIO for RPS
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (3 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 04/12] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:30         ` Chris Wilson
  2014-03-20  1:31       ` [PATCH 06/12] drm/i915: remove rps local variables Ben Widawsky
                         ` (6 subsequent siblings)
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

The values created at initialization must always exist to use the
interface. Reading them again is confusing, and pointless.

More cleanups are coming in the next patch. Since I am not 100% certain,
moreover on BYT, (though I am extremely close to that) that there is no
need to leave the MMIO here, I wanted to make it a separate patch for
the bisectable 'just-in-case'

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_sysfs.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e3fa8cd..49554d9 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -313,7 +313,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	struct drm_minor *minor = dev_to_drm_minor(kdev);
 	struct drm_device *dev = minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 val, rp_state_cap, hw_max, hw_min, non_oc_max;
+	u32 val, hw_max, hw_min, non_oc_max;
 	ssize_t ret;
 
 	ret = kstrtou32(buf, 0, &val);
@@ -327,16 +327,14 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	if (IS_VALLEYVIEW(dev_priv->dev)) {
 		val = vlv_freq_opcode(dev_priv, val);
 
-		hw_max = valleyview_rps_max_freq(dev_priv);
-		hw_min = valleyview_rps_min_freq(dev_priv);
-		non_oc_max = hw_max;
+		non_oc_max = hw_max = dev_priv->rps.max_freq;
+		hw_min = dev_priv->rps.min_freq;
 	} else {
 		val /= GT_FREQUENCY_MULTIPLIER;
 
-		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 		hw_max = dev_priv->rps.max_freq;
-		non_oc_max = (rp_state_cap & 0xff);
-		hw_min = ((rp_state_cap & 0xff0000) >> 16);
+		non_oc_max = dev_priv->rps.rp0_freq;
+		hw_min = dev_priv->rps.min_freq;
 	}
 
 	if (val < hw_min || val > hw_max ||
@@ -394,7 +392,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	struct drm_minor *minor = dev_to_drm_minor(kdev);
 	struct drm_device *dev = minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 val, rp_state_cap, hw_max, hw_min;
+	u32 val, hw_max, hw_min;
 	ssize_t ret;
 
 	ret = kstrtou32(buf, 0, &val);
@@ -408,14 +406,13 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	if (IS_VALLEYVIEW(dev)) {
 		val = vlv_freq_opcode(dev_priv, val);
 
-		hw_max = valleyview_rps_max_freq(dev_priv);
-		hw_min = valleyview_rps_min_freq(dev_priv);
+		hw_max = dev_priv->rps.max_freq;
+		hw_min = dev_priv->rps.min_freq;
 	} else {
 		val /= GT_FREQUENCY_MULTIPLIER;
 
-		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 		hw_max = dev_priv->rps.max_freq;
-		hw_min = ((rp_state_cap & 0xff0000) >> 16);
+		hw_min = dev_priv->rps.min_freq;
 	}
 
 	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
-- 
1.9.0

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

* [PATCH 06/12] drm/i915: remove rps local variables
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (4 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 05/12] drm/i915: Remove extraneous MMIO for RPS Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:30         ` Chris Wilson
  2014-03-20  1:31       ` [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0 Ben Widawsky
                         ` (5 subsequent siblings)
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

With the renamed RPS struct members, it's easier to skip the local
variables which no longer clarify anything, and if anything just make
the code harder to read.

The real motivation for this patch is actually the next patch, which
attempts to consolidate some of the functionality.

Cc: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_sysfs.c | 36 ++++++++++++-----------------------
 drivers/gpu/drm/i915/intel_pm.c   | 40 ++++++++++++++++++++-------------------
 2 files changed, 33 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 49554d9..9c57029 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -313,7 +313,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	struct drm_minor *minor = dev_to_drm_minor(kdev);
 	struct drm_device *dev = minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 val, hw_max, hw_min, non_oc_max;
+	u32 val;
 	ssize_t ret;
 
 	ret = kstrtou32(buf, 0, &val);
@@ -324,26 +324,19 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev_priv->dev)) {
+	if (IS_VALLEYVIEW(dev_priv->dev))
 		val = vlv_freq_opcode(dev_priv, val);
-
-		non_oc_max = hw_max = dev_priv->rps.max_freq;
-		hw_min = dev_priv->rps.min_freq;
-	} else {
+	else
 		val /= GT_FREQUENCY_MULTIPLIER;
 
-		hw_max = dev_priv->rps.max_freq;
-		non_oc_max = dev_priv->rps.rp0_freq;
-		hw_min = dev_priv->rps.min_freq;
-	}
-
-	if (val < hw_min || val > hw_max ||
+	if (val < dev_priv->rps.min_freq ||
+	    val > dev_priv->rps.max_freq ||
 	    val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	if (val > non_oc_max)
+	if (val > dev_priv->rps.rp0_freq)
 		DRM_DEBUG("User requested overclocking to %d\n",
 			  val * GT_FREQUENCY_MULTIPLIER);
 
@@ -392,7 +385,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	struct drm_minor *minor = dev_to_drm_minor(kdev);
 	struct drm_device *dev = minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 val, hw_max, hw_min;
+	u32 val;
 	ssize_t ret;
 
 	ret = kstrtou32(buf, 0, &val);
@@ -403,19 +396,14 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev))
 		val = vlv_freq_opcode(dev_priv, val);
-
-		hw_max = dev_priv->rps.max_freq;
-		hw_min = dev_priv->rps.min_freq;
-	} else {
+	else
 		val /= GT_FREQUENCY_MULTIPLIER;
 
-		hw_max = dev_priv->rps.max_freq;
-		hw_min = dev_priv->rps.min_freq;
-	}
-
-	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) {
+	if (val < dev_priv->rps.min_freq ||
+	    val > dev_priv->rps.max_freq ||
+	    val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3db7c40..fd68f93 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3324,7 +3324,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	u32 rp_state_cap, hw_max, hw_min;
+	u32 rp_state_cap;
 	u32 gt_perf_status;
 	u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
 	u32 gtfifodbg;
@@ -3353,21 +3353,22 @@ static void gen6_enable_rps(struct drm_device *dev)
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
 	/* All of these values are in units of 50MHz */
-	dev_priv->rps.cur_freq = 0;
-	/* hw_max = RP0 until we check for overclocking */
-	dev_priv->rps.max_freq = hw_max = rp_state_cap & 0xff;
+	dev_priv->rps.cur_freq		= 0;
 	/* static values from HW: RP0 < RPe < RP1 < RPn (min_freq) */
-	dev_priv->rps.rp1_freq = (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.rp0_freq = (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq;
-	dev_priv->rps.min_freq = hw_min = (rp_state_cap >> 16) & 0xff;
+	dev_priv->rps.rp1_freq		= (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.rp0_freq		= (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.min_freq		= (rp_state_cap >> 16) & 0xff;
+	/* XXX: only BYT has a special efficient freq */
+	dev_priv->rps.efficient_freq	= dev_priv->rps.rp1_freq;
+	/* hw_max = RP0 until we check for overclocking */
+	dev_priv->rps.max_freq		= dev_priv->rps.rp0_freq;
 
 	/* Preserve min/max settings in case of re-init */
 	if (dev_priv->rps.max_freq_softlimit == 0)
-		dev_priv->rps.max_freq_softlimit = hw_max;
+		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 = hw_min;
+		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -3597,7 +3598,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	u32 gtfifodbg, val, hw_max, hw_min, rc6_mode = 0;
+	u32 gtfifodbg, val, rc6_mode = 0;
 	int i;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -3657,27 +3658,28 @@ 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 = hw_max = valleyview_rps_max_freq(dev_priv);
+	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, hw_max),
-			 hw_max);
+			 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);
 
-	hw_min = valleyview_rps_min_freq(dev_priv);
+	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, hw_min),
-			 hw_min);
+			 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 = hw_max;
+		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 = hw_min;
+		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),
-- 
1.9.0

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

* [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (5 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 06/12] drm/i915: remove rps local variables Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:24         ` Chris Wilson
  2014-03-20  1:31       ` [PATCH 08/12] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
                         ` (4 subsequent siblings)
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

Programming it outside of the rp0-rp1 range is considered a programming
error. Since we do not know that the previous value would actually be in
the range, program something we've read from the hardware, and therefore
know will work.

This is potentially an issue for platforms whose ranges are outside the
norms given in the programming guide (ie. early silicon)

v2: Use RP1 instead of RPn

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index fd68f93..8a64ecc 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3285,8 +3285,10 @@ static void gen8_enable_rps(struct drm_device *dev)
 				    rc6_mask);
 
 	/* 4 Program defaults and thresholds for RPS*/
-	I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
-	I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(12)); /* Request 600 MHz */
+	I915_WRITE(GEN6_RPNSWREQ,
+		   HSW_FREQUENCY(dev_priv->rps.rp1_freq));
+	I915_WRITE(GEN6_RC_VIDEO_FREQ,
+		   HSW_FREQUENCY(dev_priv->rps.rp1_freq));
 	/* NB: Docs say 1s, and 1000000 - which aren't equivalent */
 	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */
 
-- 
1.9.0

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

* [PATCH 08/12] drm/i915/bdw: Extract rp_state_caps logic
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (6 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0 Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:28         ` Chris Wilson
  2014-03-20  1:31       ` [PATCH 09/12] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
                         ` (3 subsequent siblings)
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

We have a need for duplicated parsing of the RP_STATE_CAPS register (and
the setting of the associated fields). To reuse some code, we can
extract the function into a simple helper.

This patch also addresses the fact that we missed doing this for gen8,
something we should have done anyway.

This could be two patches, one to extract, and one to add gen8, but it's
trivial enough that I think one is fine. I will accept a request to
split it. Please notice the fix addressed by v2 below.

Valleyview is left untouched because it is different.

v2: Logically rebased on top of
commit dd0a1aa19bd3d7203e58157b84cea78bbac605ac
Author: Jeff McGee <jeff.mcgee@intel.com>
Date:   Tue Feb 4 11:32:31 2014 -0600

    drm/i915: Restore rps/rc6 on reset

Note with the above change the fix for gen8 is also handled (which was
not the case in Jeff's original patch).

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_pm.c | 40 +++++++++++++++++++++++-----------------
 1 file changed, 23 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 8a64ecc..ab9e992 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3248,6 +3248,27 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev)
 	I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs);
 }
 
+static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_cap)
+{
+	/* All of these values are in units of 50MHz */
+	dev_priv->rps.cur_freq		= 0;
+	/* static values from HW: RP0 < RPe < RP1 < RPn (min_freq) */
+	dev_priv->rps.rp1_freq		= (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.rp0_freq		= (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.min_freq		= (rp_state_cap >> 16) & 0xff;
+	/* XXX: only BYT has a special efficient freq */
+	dev_priv->rps.efficient_freq	= dev_priv->rps.rp1_freq;
+	/* hw_max = RP0 until we check for overclocking */
+	dev_priv->rps.max_freq		= dev_priv->rps.rp0_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;
+}
+
 static void gen8_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3266,6 +3287,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* 2b: Program RC6 thresholds.*/
 	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
@@ -3354,23 +3376,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
-	/* All of these values are in units of 50MHz */
-	dev_priv->rps.cur_freq		= 0;
-	/* static values from HW: RP0 < RPe < RP1 < RPn (min_freq) */
-	dev_priv->rps.rp1_freq		= (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.rp0_freq		= (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.min_freq		= (rp_state_cap >> 16) & 0xff;
-	/* XXX: only BYT has a special efficient freq */
-	dev_priv->rps.efficient_freq	= dev_priv->rps.rp1_freq;
-	/* hw_max = RP0 until we check for overclocking */
-	dev_priv->rps.max_freq		= dev_priv->rps.rp0_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;
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
-- 
1.9.0

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

* [PATCH 09/12] drm/i915/bdw: RPS frequency bits are the same as HSW
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (7 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 08/12] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  1:31       ` [PATCH 10/12] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
                         ` (2 subsequent siblings)
  11 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 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 ab9e992..9486396 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3028,7 +3028,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 
 	gen6_set_rps_thresholds(dev_priv, val);
 
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		I915_WRITE(GEN6_RPNSWREQ,
 			   HSW_FREQUENCY(val));
 	else
-- 
1.9.0

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

* [PATCH 10/12] drm/i915/bdw: Implement a basic PM interrupt handler
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (8 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 09/12] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-24 19:30         ` Ben Widawsky
  2014-03-20  1:31       ` [PATCH 11/12] drm/i915/bdw: Ensure a context is loaded before RC6 Ben Widawsky
  2014-03-20  1:31       ` [PATCH 12/12] drm/i915/bdw: Enable RC6 Ben Widawsky
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

Almost all of it is reusable from the existing code. The primary
difference is we need to do even less in the interrupt handler, since
interrupts are not shared in the same way.

The patch is mostly a copy-paste of the existing snb+ code, with updates
to the relevant parts requiring changes to the interrupt handling. As
such it /should/ be relatively trivial. It's highly likely that I missed
some places where I need a gen8 version of the PM interrupts, but it has
become invisible to me by now.

This patch could probably be split into adding the new functions,
followed by actually handling the interrupts. Since the code is
currently disabled (and broken) I think the patch stands better by
itself.

v2: Move the commit about not touching the ringbuffer interrupt to the
snb_* function where it belongs (Rodrigo)

v3: Rebased on Paulo's runtime PM changes

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_irq.c  | 84 +++++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_drv.h |  2 +
 drivers/gpu/drm/i915/intel_pm.c  | 39 ++++++++++++++++++-
 4 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4b4aeb3..2f9ec6e 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -175,6 +175,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
 		return;
 	}
 
+	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
 	new_val = dev_priv->pm_irq_mask;
 	new_val &= ~interrupt_mask;
 	new_val |= (~enabled_irq_mask & interrupt_mask);
@@ -214,6 +215,53 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
 	return true;
 }
 
+/**
+  * bdw_update_pm_irq - update GT interrupt 2
+  * @dev_priv: driver private
+  * @interrupt_mask: mask of interrupt bits to update
+  * @enabled_irq_mask: mask of interrupt bits to enable
+  *
+  * Copied from the snb function, updated with relevant register offsets
+  */
+static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
+			      uint32_t interrupt_mask,
+			      uint32_t enabled_irq_mask)
+{
+	uint32_t new_val;
+
+	assert_spin_locked(&dev_priv->irq_lock);
+
+	if (dev_priv->pm.irqs_disabled) {
+		WARN(1, "IRQs disabled\n");
+		dev_priv->pm.regsave.gen6_pmimr &= ~interrupt_mask;
+		dev_priv->pm.regsave.gen6_pmimr |= (~enabled_irq_mask &
+						     interrupt_mask);
+		return;
+	}
+
+	new_val = dev_priv->pm_irq_mask;
+	new_val &= ~interrupt_mask;
+	new_val |= (~enabled_irq_mask & interrupt_mask);
+
+	if (new_val != dev_priv->pm_irq_mask) {
+		dev_priv->pm_irq_mask = new_val;
+		I915_WRITE(GEN8_GT_IMR(2), I915_READ(GEN8_GT_IMR(2)) |
+					   dev_priv->pm_irq_mask);
+		POSTING_READ(GEN8_GT_IMR(2));
+	}
+}
+
+void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+{
+	bdw_update_pm_irq(dev_priv, mask, mask);
+}
+
+void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+{
+	bdw_update_pm_irq(dev_priv, mask, 0);
+}
+
+
 static bool cpt_can_enable_serr_int(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1131,13 +1179,16 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	spin_lock_irq(&dev_priv->irq_lock);
 	pm_iir = dev_priv->rps.pm_iir;
 	dev_priv->rps.pm_iir = 0;
-	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
-	snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	if (IS_BROADWELL(dev_priv->dev))
+		bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	else {
+		snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+		/* Make sure we didn't queue anything we're not going to
+		 * process. */
+		WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
+	}
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	/* Make sure we didn't queue anything we're not going to process. */
-	WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
-
 	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
 		return;
 
@@ -1330,6 +1381,19 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 		ivybridge_parity_error_irq_handler(dev, gt_iir);
 }
 
+static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
+{
+	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
+		return;
+
+	spin_lock(&dev_priv->irq_lock);
+	dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
+	bdw_disable_pm_irq(dev_priv, pm_iir & GEN6_PM_RPS_EVENTS);
+	spin_unlock(&dev_priv->irq_lock);
+
+	queue_work(dev_priv->wq, &dev_priv->rps.work);
+}
+
 static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
 				       struct drm_i915_private *dev_priv,
 				       u32 master_ctl)
@@ -1365,6 +1429,16 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
 			DRM_ERROR("The master control interrupt lied (GT1)!\n");
 	}
 
+	if (master_ctl & GEN8_GT_PM_IRQ) {
+		tmp = I915_READ(GEN8_GT_IIR(2));
+		if (tmp & GEN6_PM_RPS_EVENTS) {
+			ret = IRQ_HANDLED;
+			gen8_rps_irq_handler(dev_priv, tmp);
+			I915_WRITE(GEN8_GT_IIR(1), tmp & GEN6_PM_RPS_EVENTS);
+		} else
+			DRM_ERROR("The master control interrupt lied (PM)!\n");
+	}
+
 	if (master_ctl & GEN8_GT_VECS_IRQ) {
 		tmp = I915_READ(GEN8_GT_IIR(3));
 		if (tmp) {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 6174fda..67952c7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4086,6 +4086,7 @@ enum punit_power_well {
 #define  GEN8_DE_PIPE_A_IRQ		(1<<16)
 #define  GEN8_DE_PIPE_IRQ(pipe)		(1<<(16+pipe))
 #define  GEN8_GT_VECS_IRQ		(1<<6)
+#define  GEN8_GT_PM_IRQ			(1<<4)
 #define  GEN8_GT_VCS2_IRQ		(1<<3)
 #define  GEN8_GT_VCS1_IRQ		(1<<2)
 #define  GEN8_GT_BCS_IRQ		(1<<1)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 60ffad3..fde5df7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -623,6 +623,8 @@ void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void hsw_runtime_pm_disable_interrupts(struct drm_device *dev);
 void hsw_runtime_pm_restore_interrupts(struct drm_device *dev);
+void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 
 
 /* intel_crt.c */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 9486396..38e4d60 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3155,6 +3155,25 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
 
+static void gen8_disable_rps_interrupts(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+	I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) &
+				   ~GEN6_PM_RPS_EVENTS);
+	/* Complete PM interrupt masking here doesn't race with the rps work
+	 * item again unmasking PM interrupts because that is using a different
+	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
+
+	spin_lock_irq(&dev_priv->irq_lock);
+	dev_priv->rps.pm_iir = 0;
+	spin_unlock_irq(&dev_priv->irq_lock);
+
+	I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
+}
+
 static void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3180,7 +3199,10 @@ static void gen6_disable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
 
-	gen6_disable_rps_interrupts(dev);
+	if (IS_BROADWELL(dev))
+		gen8_disable_rps_interrupts(dev);
+	else
+		gen6_disable_rps_interrupts(dev);
 }
 
 static void valleyview_disable_rps(struct drm_device *dev)
@@ -3225,6 +3247,19 @@ int intel_enable_rc6(const struct drm_device *dev)
 	return INTEL_RC6_ENABLE;
 }
 
+static void gen8_enable_rps_interrupts(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	spin_lock_irq(&dev_priv->irq_lock);
+	WARN_ON(dev_priv->rps.pm_iir);
+	bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
+	I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
+	spin_unlock_irq(&dev_priv->irq_lock);
+
+	I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
+}
+
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3339,7 +3374,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
 	gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
 
-	gen6_enable_rps_interrupts(dev);
+	gen8_enable_rps_interrupts(dev);
 
 	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
-- 
1.9.0

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

* [PATCH 11/12] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (9 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 10/12] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-20  7:35         ` Chris Wilson
  2014-03-20  1:31       ` [PATCH 12/12] drm/i915/bdw: Enable RC6 Ben Widawsky
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

RC6 works a lot like HW contexts in that when the GPU enters RC6 it
saves away the state to a context, and loads it upon wake.

It's to be somewhat expected that BIOS will not set up valid GPU state.
As a result, if loading bad state can cause the GPU to get angry, it
would make sense then that we need to load state first. There are two
ways in which we can do this:

1. Create 3d state in the driver, load it up, then enable RC6.
1b. Reuse a known good state, [and if needed,] just bind objects where
needed. Then enable RC6.
2. Hold off enabling RC6 until userspace has had a chance to complete
batches.

There has been discussions in the past with #1 as it has been
recommended for fixes elsewhere. I'm not opposed to it, I'd just like to
do the easy thing now to enable the platform.

This patch is a hack that implement option #2. It will defer enabling
rc6 until the first batch from userspace has been retired. It suffers
two flaws. The first is, if the driver is loaded, but a batch is not
submitted/completed, we'll never enter rc6. The other is, it expects
userspace to submit a batch with 3d state first. Both of these things
are not actual flaws for most users because most users will boot to a
graphical composited desktop. Both mesa, and X will always emit the
necessary 3d state.

Once a context is loaded and we enable rc6, the default context should
inherit the proper state because we always inhibit the restore for the
default context. This assumes certain things about the workaround/issue
itself to which I am not privy (primarily that the indirect state
objects don't actually need to exist).

With that, there are currently 4 options for BDW:
1. Don't use RC6.
2. Use RC6 and expect a hang on the first batch submitted for every
context.
3. Use RC6 and use this patch.
4. Wait for another workaround implementation.

NOTE: This patch could be used against other platforms as well.

v2: Re-add accidentally dropped hunk (Ben)

v3: Now more compilable (Ben)

v4: Use the existing enable flag for rc6. This will also make the
suspend/resume case work properly, which is broken in v3.
Disable rc6 on reset, and defer re-enabling until the first batch.

The fact that RC6 residency continues to increment, and that this patch
prevents a hang on BDW silicon has been:
Tested-by: Kenneth Graunke <kenneth@whitecape.org> (v1)

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_drv.c      |  4 +++-
 drivers/gpu/drm/i915/i915_gem.c      | 10 ++++++++++
 drivers/gpu/drm/i915/intel_display.c |  5 +++++
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index fa5d0ed..4dc18ea 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -672,6 +672,8 @@ int i915_reset(struct drm_device *dev)
 	mutex_lock(&dev->struct_mutex);
 
 	i915_gem_reset(dev);
+	if (IS_BROADWELL(dev))
+		intel_disable_gt_powersave(dev);
 
 	simulated = dev_priv->gpu_error.stop_rings != 0;
 
@@ -726,7 +728,7 @@ 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) {
+		if (INTEL_INFO(dev)->gen > 5 && !IS_BROADWELL(dev)) {
 			mutex_lock(&dev->struct_mutex);
 			intel_enable_gt_powersave(dev);
 			mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ee32759..4de8800 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2436,6 +2436,7 @@ void i915_gem_reset(struct drm_device *dev)
 static void
 i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 {
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	uint32_t seqno;
 
 	if (list_empty(&ring->request_list))
@@ -2459,6 +2460,15 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
 			break;
 
+		/* Wa: can't find the w/a name.
+		 * This doesn't actually implement the w/a, but it a workaround
+		 * for the workaround. It defers using rc6 until we know valid
+		 * state exists.
+		 */
+		if (IS_BROADWELL(ring->dev) && intel_enable_rc6(ring->dev) &&
+		    !dev_priv->rps.enabled && ring->id == RCS)
+			intel_enable_gt_powersave(ring->dev);
+
 		i915_gem_object_move_to_inactive(obj);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0b19afd..12055c9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11221,6 +11221,11 @@ void intel_modeset_init_hw(struct drm_device *dev)
 
 	intel_reset_dpio(dev);
 
+	if (IS_BROADWELL(dev)) {
+		DRM_DEBUG_DRIVER("Deferring RC6 enabling until first batch is complete\n");
+		return;
+	}
+
 	mutex_lock(&dev->struct_mutex);
 	intel_enable_gt_powersave(dev);
 	mutex_unlock(&dev->struct_mutex);
-- 
1.9.0

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

* [PATCH 12/12] drm/i915/bdw: Enable RC6
  2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
                         ` (10 preceding siblings ...)
  2014-03-20  1:31       ` [PATCH 11/12] drm/i915/bdw: Ensure a context is loaded before RC6 Ben Widawsky
@ 2014-03-20  1:31       ` Ben Widawsky
  2014-03-24 10:27         ` Deepak S
  11 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-20  1:31 UTC (permalink / raw)
  To: Intel GFX

It is tested and looking fairly stable now, so turn it on. It wasn't
intentionally turned off originally :P

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 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 38e4d60..8e98042 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4518,7 +4518,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		ironlake_enable_drps(dev);
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
 		if (IS_VALLEYVIEW(dev))
 			valleyview_setup_pctx(dev);
 		/*
-- 
1.9.0

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

* Re: [PATCH 04/12] drm/i915: Rename and comment all the RPS *stuff*
  2014-03-20  1:31       ` [PATCH 04/12] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
@ 2014-03-20  7:01         ` Chris Wilson
  0 siblings, 0 replies; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:01 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:11PM -0700, Ben Widawsky wrote:
> The names of the struct members for RPS are stupid. Every time I need to
> do anything in this code I have to spend a significant amount of time to
> remember what it all means. By renaming the variables (and adding the
> comments) I hope to clear up the situation. Indeed doing this make some
> upcoming patches more readable.
> 
> I've avoided ILK because it's possible that the naming used for Ironlake
> matches what is in the docs. I believe the ILK power docs were never
> published, and I am too lazy to dig them up.
> 
> v2: leave rp0, and rp1 in the names. It is useful to have these limits
> available at times. min_freq and max_freq (which may be equal to rp0, or
> rp1 depending on the platform) represent the actual HW min and max.
> 
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>

I didn't spot any changes that were incorrect, so
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 01/12] drm/i915: Reorganize the overclock code
  2014-03-20  1:31       ` [PATCH 01/12] drm/i915: Reorganize the overclock code Ben Widawsky
@ 2014-03-20  7:23         ` Chris Wilson
  0 siblings, 0 replies; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:23 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:08PM -0700, Ben Widawsky wrote:
> The existing code (which I changed last) was very convoluted. I believe
> it was attempting to skip the overclock portion if the previous pcode
> write failed. When I last touched the code, I was preserving this
> behavior. There is some benefit to doing it that way in that if the
> first pcode access fails, the later is likely invalid.
> 
> Having a bit more confidence in my understanding of how things work, I
> now feel it's better to have clear, readable, code than to try to skip
> over this one operation in an unusual case.
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0
  2014-03-20  1:31       ` [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0 Ben Widawsky
@ 2014-03-20  7:24         ` Chris Wilson
  2014-03-22 18:42           ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:24 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:14PM -0700, Ben Widawsky wrote:
> Programming it outside of the rp0-rp1 range is considered a programming
> error. Since we do not know that the previous value would actually be in
> the range, program something we've read from the hardware, and therefore
> know will work.
> 
> This is potentially an issue for platforms whose ranges are outside the
> norms given in the programming guide (ie. early silicon)
> 
> v2: Use RP1 instead of RPn
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>

Do you have a reference for GEN6_RC_VIDEO_FREQ? I still have no idea
what that controls, nor its valid range.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 08/12] drm/i915/bdw: Extract rp_state_caps logic
  2014-03-20  1:31       ` [PATCH 08/12] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
@ 2014-03-20  7:28         ` Chris Wilson
  2014-03-22 18:46           ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:28 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:15PM -0700, Ben Widawsky wrote:
> We have a need for duplicated parsing of the RP_STATE_CAPS register (and
> the setting of the associated fields). To reuse some code, we can
> extract the function into a simple helper.
> 
> This patch also addresses the fact that we missed doing this for gen8,
> something we should have done anyway.
> 
> This could be two patches, one to extract, and one to add gen8, but it's
> trivial enough that I think one is fine. I will accept a request to
> split it. Please notice the fix addressed by v2 below.
> 
> Valleyview is left untouched because it is different.
> 
> v2: Logically rebased on top of
> commit dd0a1aa19bd3d7203e58157b84cea78bbac605ac
> Author: Jeff McGee <jeff.mcgee@intel.com>
> Date:   Tue Feb 4 11:32:31 2014 -0600
> 
>     drm/i915: Restore rps/rc6 on reset
> 
> Note with the above change the fix for gen8 is also handled (which was
> not the case in Jeff's original patch).
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

By setting max_freq_soft before querying overclocking frequencies, we
force the user to have to manually raise the max freq through sysfs,
right? Hasn't the user already explicitly asked for overclocking through
the BIOS setting in the first place, so isn't that a needless burden
upon the user?
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 03/12] drm/i915: Store the HW min frequency as min_freq
  2014-03-20  1:31       ` [PATCH 03/12] drm/i915: Store the HW min frequency as min_freq Ben Widawsky
@ 2014-03-20  7:29         ` Chris Wilson
  2014-03-24 10:31         ` Deepak S
  1 sibling, 0 replies; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:29 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:10PM -0700, Ben Widawsky wrote:
> this leaves a temporarily awkward min_delay (the soft limit) with the
> new min_freq (the hardware limit). It's fixed in the next patch.
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 05/12] drm/i915: Remove extraneous MMIO for RPS
  2014-03-20  1:31       ` [PATCH 05/12] drm/i915: Remove extraneous MMIO for RPS Ben Widawsky
@ 2014-03-20  7:30         ` Chris Wilson
  0 siblings, 0 replies; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:30 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:12PM -0700, Ben Widawsky wrote:
> The values created at initialization must always exist to use the
> interface. Reading them again is confusing, and pointless.
> 
> More cleanups are coming in the next patch. Since I am not 100% certain,
> moreover on BYT, (though I am extremely close to that) that there is no
> need to leave the MMIO here, I wanted to make it a separate patch for
> the bisectable 'just-in-case'
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>

Thank you.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 06/12] drm/i915: remove rps local variables
  2014-03-20  1:31       ` [PATCH 06/12] drm/i915: remove rps local variables Ben Widawsky
@ 2014-03-20  7:30         ` Chris Wilson
  2014-03-20 13:46           ` Daniel Vetter
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:30 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:13PM -0700, Ben Widawsky wrote:
> With the renamed RPS struct members, it's easier to skip the local
> variables which no longer clarify anything, and if anything just make
> the code harder to read.
> 
> The real motivation for this patch is actually the next patch, which
> attempts to consolidate some of the functionality.
> 
> Cc: Jeff McGee <jeff.mcgee@intel.com>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 02/12] drm/i915: Fix coding style for RPS
  2014-03-20  1:31       ` [PATCH 02/12] drm/i915: Fix coding style for RPS Ben Widawsky
@ 2014-03-20  7:31         ` Chris Wilson
  2014-03-24 10:30         ` Deepak S
  1 sibling, 0 replies; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:31 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:09PM -0700, Ben Widawsky wrote:
> Introduced:
> commit b8a5ff8d7c676a04e0da5ec16bb068dd39459042
> Author: Jeff McGee <jeff.mcgee@intel.com>
> Date:   Tue Feb 4 11:37:01 2014 -0600
> 
>     drm/i915: Update rps interrupt limits
> 
> Cc: Jeff McGee <jeff.mcgee@intel.com>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>

The trailing {} is overkill, but forgivable :-p
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 11/12] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-03-20  1:31       ` [PATCH 11/12] drm/i915/bdw: Ensure a context is loaded before RC6 Ben Widawsky
@ 2014-03-20  7:35         ` Chris Wilson
  0 siblings, 0 replies; 97+ messages in thread
From: Chris Wilson @ 2014-03-20  7:35 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Wed, Mar 19, 2014 at 06:31:18PM -0700, Ben Widawsky wrote:
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index ee32759..4de8800 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2436,6 +2436,7 @@ void i915_gem_reset(struct drm_device *dev)
>  static void
>  i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
>  {
> +	struct drm_i915_private *dev_priv = ring->dev->dev_private;
>  	uint32_t seqno;
>  
>  	if (list_empty(&ring->request_list))
> @@ -2459,6 +2460,15 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
>  		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
>  			break;
>  
> +		/* Wa: can't find the w/a name.
> +		 * This doesn't actually implement the w/a, but it a workaround
> +		 * for the workaround. It defers using rc6 until we know valid
> +		 * state exists.
> +		 */
> +		if (IS_BROADWELL(ring->dev) && intel_enable_rc6(ring->dev) &&
> +		    !dev_priv->rps.enabled && ring->id == RCS)
> +			intel_enable_gt_powersave(ring->dev);
> +

This is a big eyesore. I think we will both be happy if you move this to
intel_mark_idle(). You can then check for ring[RCS]->last_context being
set.

>  		i915_gem_object_move_to_inactive(obj);
>  	}

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 11/11] [v4] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-03-20  0:41               ` Ben Widawsky
@ 2014-03-20 13:42                 ` Daniel Vetter
  2014-03-20 17:30                   ` Jesse Barnes
  0 siblings, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2014-03-20 13:42 UTC (permalink / raw)
  To: Ben Widawsky
  Cc: David E. Box, Intel GFX, Kristen Carlson Accardi, Ben Widawsky

On Wed, Mar 19, 2014 at 05:41:37PM -0700, Ben Widawsky wrote:
> I can't say it's completely unexpected that this would be your response,
> but I do feel like you've ignored my argument that this is better than
> the current situation. Not merging this patch only keeps things bad.
> 
> So I'd like you to re-consider merging this patch instead of waiting for
> the perfect solution. This patch requires a lot less review than the
> real fix. It has been tested by several people (I can ask them to put
> their reviewed by on it). It enables rc6 for people today, and this
> includes pc7, and deeper package and C states. It's very easy to revert
> if/when we get a real fix. Real users benefit from this patch. Real
> users are not hurt by this patch because if userspace is submitting bad
> state setup, they'll have the same or worse experience than failing RC6.
> 
> As an aside, this needs to come before I enable rc6 anyway. So the order
> way bad.

I fully agree with your assessment on technical reasons. The problem is
that I've just been forced through an exercise of "merge this now because
it works, people have tested it and we really, really, really need it to
move forward" and it didn't go down well.

Which means for the foreseeable future I'll reject patches when it looks
like a few too many rolls of ducttape have been involved in their
construction. I'd prefer if we could move more towards a merge early or at
least integration-test early model, but currently that's not a viable
model for me.

Note that this is not an iron rule at all, e.g. with psr I've just told
Rodrigo that I want the current state of affairs finalized for merging
instead of trying to hunt for the perfect patches. The reason for that was
that I think the remaining issues in psr support are well-understood and
we have solid test-coverage to make sure we don't fumble things. Also one
issue with the current psr patches is that they're way too conservative in
a few cases (i.e. wasting power), but for something tricky leaning towards
correctness is actually a feature. And bad power numbers tend to grab our
project managements attention. Overall the risks are a fairly clear
quantity.

In this area of rc6 and contexts though we have track record of not really
understanding issues. Which means that the risks here are unknown and
might be fairly big.

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

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

* Re: [PATCH 06/12] drm/i915: remove rps local variables
  2014-03-20  7:30         ` Chris Wilson
@ 2014-03-20 13:46           ` Daniel Vetter
  0 siblings, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2014-03-20 13:46 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Intel GFX

On Thu, Mar 20, 2014 at 07:30:52AM +0000, Chris Wilson wrote:
> On Wed, Mar 19, 2014 at 06:31:13PM -0700, Ben Widawsky wrote:
> > With the renamed RPS struct members, it's easier to skip the local
> > variables which no longer clarify anything, and if anything just make
> > the code harder to read.
> > 
> > The real motivation for this patch is actually the next patch, which
> > attempts to consolidate some of the functionality.
> > 
> > Cc: Jeff McGee <jeff.mcgee@intel.com>
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

Merged up to this one to not have a badly diverging codebase between 3.15
and later kernels. Thanks for patches&review.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 11/11] [v4] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-03-20 13:42                 ` Daniel Vetter
@ 2014-03-20 17:30                   ` Jesse Barnes
  2014-03-20 20:12                     ` Jesse Barnes
  0 siblings, 1 reply; 97+ messages in thread
From: Jesse Barnes @ 2014-03-20 17:30 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David E. Box, Ben Widawsky, Intel GFX, Kristen Carlson Accardi,
	Ben Widawsky

On Thu, 20 Mar 2014 14:42:32 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Wed, Mar 19, 2014 at 05:41:37PM -0700, Ben Widawsky wrote:
> > I can't say it's completely unexpected that this would be your response,
> > but I do feel like you've ignored my argument that this is better than
> > the current situation. Not merging this patch only keeps things bad.
> > 
> > So I'd like you to re-consider merging this patch instead of waiting for
> > the perfect solution. This patch requires a lot less review than the
> > real fix. It has been tested by several people (I can ask them to put
> > their reviewed by on it). It enables rc6 for people today, and this
> > includes pc7, and deeper package and C states. It's very easy to revert
> > if/when we get a real fix. Real users benefit from this patch. Real
> > users are not hurt by this patch because if userspace is submitting bad
> > state setup, they'll have the same or worse experience than failing RC6.
> > 
> > As an aside, this needs to come before I enable rc6 anyway. So the order
> > way bad.
> 
> I fully agree with your assessment on technical reasons. The problem is
> that I've just been forced through an exercise of "merge this now because
> it works, people have tested it and we really, really, really need it to
> move forward" and it didn't go down well.
> 
> Which means for the foreseeable future I'll reject patches when it looks
> like a few too many rolls of ducttape have been involved in their
> construction. I'd prefer if we could move more towards a merge early or at
> least integration-test early model, but currently that's not a viable
> model for me.
> 
> Note that this is not an iron rule at all, e.g. with psr I've just told
> Rodrigo that I want the current state of affairs finalized for merging
> instead of trying to hunt for the perfect patches. The reason for that was
> that I think the remaining issues in psr support are well-understood and
> we have solid test-coverage to make sure we don't fumble things. Also one
> issue with the current psr patches is that they're way too conservative in
> a few cases (i.e. wasting power), but for something tricky leaning towards
> correctness is actually a feature. And bad power numbers tend to grab our
> project managements attention. Overall the risks are a fairly clear
> quantity.
> 
> In this area of rc6 and contexts though we have track record of not really
> understanding issues. Which means that the risks here are unknown and
> might be fairly big.

Do you think this patch falls into that class of issues?  It seems like
it's a general improvement, even if it doesn't address the more
general behavior we'd like (sooner than later really).

But blocking it until we have the full primitive emission seems like
it's going to keep power consumption in a terrible state on BDW for the
forseeable future... moreover I guess this is something we need going
back forever for RC6 stability, at least according to the hw team.  So
rather than blocking this, maybe we should commit it for all platforms!

-- 
Jesse Barnes, Intel Open Source Technology Center

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

* Re: [PATCH 11/11] [v4] drm/i915/bdw: Ensure a context is loaded before RC6
  2014-03-20 17:30                   ` Jesse Barnes
@ 2014-03-20 20:12                     ` Jesse Barnes
  0 siblings, 0 replies; 97+ messages in thread
From: Jesse Barnes @ 2014-03-20 20:12 UTC (permalink / raw)
  To: Jesse Barnes
  Cc: Ben Widawsky, Kristen Carlson Accardi, Intel GFX, David E. Box,
	Ben Widawsky

On Thu, 20 Mar 2014 10:30:32 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> On Thu, 20 Mar 2014 14:42:32 +0100
> Daniel Vetter <daniel@ffwll.ch> wrote:
> 
> > On Wed, Mar 19, 2014 at 05:41:37PM -0700, Ben Widawsky wrote:
> > > I can't say it's completely unexpected that this would be your response,
> > > but I do feel like you've ignored my argument that this is better than
> > > the current situation. Not merging this patch only keeps things bad.
> > > 
> > > So I'd like you to re-consider merging this patch instead of waiting for
> > > the perfect solution. This patch requires a lot less review than the
> > > real fix. It has been tested by several people (I can ask them to put
> > > their reviewed by on it). It enables rc6 for people today, and this
> > > includes pc7, and deeper package and C states. It's very easy to revert
> > > if/when we get a real fix. Real users benefit from this patch. Real
> > > users are not hurt by this patch because if userspace is submitting bad
> > > state setup, they'll have the same or worse experience than failing RC6.
> > > 
> > > As an aside, this needs to come before I enable rc6 anyway. So the order
> > > way bad.
> > 
> > I fully agree with your assessment on technical reasons. The problem is
> > that I've just been forced through an exercise of "merge this now because
> > it works, people have tested it and we really, really, really need it to
> > move forward" and it didn't go down well.
> > 
> > Which means for the foreseeable future I'll reject patches when it looks
> > like a few too many rolls of ducttape have been involved in their
> > construction. I'd prefer if we could move more towards a merge early or at
> > least integration-test early model, but currently that's not a viable
> > model for me.
> > 
> > Note that this is not an iron rule at all, e.g. with psr I've just told
> > Rodrigo that I want the current state of affairs finalized for merging
> > instead of trying to hunt for the perfect patches. The reason for that was
> > that I think the remaining issues in psr support are well-understood and
> > we have solid test-coverage to make sure we don't fumble things. Also one
> > issue with the current psr patches is that they're way too conservative in
> > a few cases (i.e. wasting power), but for something tricky leaning towards
> > correctness is actually a feature. And bad power numbers tend to grab our
> > project managements attention. Overall the risks are a fairly clear
> > quantity.
> > 
> > In this area of rc6 and contexts though we have track record of not really
> > understanding issues. Which means that the risks here are unknown and
> > might be fairly big.
> 
> Do you think this patch falls into that class of issues?  It seems like
> it's a general improvement, even if it doesn't address the more
> general behavior we'd like (sooner than later really).
> 
> But blocking it until we have the full primitive emission seems like
> it's going to keep power consumption in a terrible state on BDW for the
> forseeable future... moreover I guess this is something we need going
> back forever for RC6 stability, at least according to the hw team.  So
> rather than blocking this, maybe we should commit it for all platforms!

Summarizing IRC discussion a bit: speaking generally of when some
future work blocks an existing fix or feature, we really need to make
sure someone is working on the broader task and make sure we track it
so it doesn't get lost, otherwise everyone loses.  The user loses
because a fix or feature isn't available, the author loses because
something gets blocked indefinitely, and upstream loses because either
a fix doesn't land or it does and the larger feature never gets
implemented because the pressure is off.

So with that, who wants to volunteer to update the 3D state emission
patch to include BDW and push it upstream?  Daniel promised to file a
JIRA task for this so our PM can track it, so someone will be
volunteered in the next week or so if we don't get it done before then.

-- 
Jesse Barnes, Intel Open Source Technology Center

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

* Re: [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0
  2014-03-20  7:24         ` Chris Wilson
@ 2014-03-22 18:42           ` Ben Widawsky
  2014-03-22 21:06             ` Chris Wilson
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2014-03-22 18:42 UTC (permalink / raw)
  To: Chris Wilson, Intel GFX

On Thu, Mar 20, 2014 at 07:24:38AM +0000, Chris Wilson wrote:
> On Wed, Mar 19, 2014 at 06:31:14PM -0700, Ben Widawsky wrote:
> > Programming it outside of the rp0-rp1 range is considered a programming
> > error. Since we do not know that the previous value would actually be in
> > the range, program something we've read from the hardware, and therefore
> > know will work.
> > 
> > This is potentially an issue for platforms whose ranges are outside the
> > norms given in the programming guide (ie. early silicon)
> > 
> > v2: Use RP1 instead of RPn
> > 
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> 
> Do you have a reference for GEN6_RC_VIDEO_FREQ? I still have no idea
> what that controls, nor its valid range.
> -Chris
> 

I have no reference for the video freq other than the brief mention in
the programming guide, and know nothing more than you do about it. It's
there because the original spec I had said to program it to 600MHz. The
reason for /this/ patch was that I noticed the default values happened
to be a *really* close to our max freq. and figured someone, somewhere
might get a part whose lower, or upper bound precludes setting the
constant provided in the programming guide.

Interestingly, the programming guide has been updated since I originally
wrote this patch to clearly indicate both of these registers need to be
programmed between Rp1-Rp0. So I guess that means that Rp1-Rp0 is the
valid range. Therefore, I think we should either proceed with this
patch, or create a new patch to avoid writing it at all. The current
code seems like the worst solution of all.

If you want to argue we can drop the write to GEN6_RPNSWREQ since we do
the correct thing after step 6:
gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);

I wouldn't be too opposed. I was just trying to follow the spec as
closely as possible, and it says to write the register value in this
sequence, so I did.

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 08/12] drm/i915/bdw: Extract rp_state_caps logic
  2014-03-20  7:28         ` Chris Wilson
@ 2014-03-22 18:46           ` Ben Widawsky
  0 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-03-22 18:46 UTC (permalink / raw)
  To: Chris Wilson, Intel GFX

On Thu, Mar 20, 2014 at 07:28:29AM +0000, Chris Wilson wrote:
> On Wed, Mar 19, 2014 at 06:31:15PM -0700, Ben Widawsky wrote:
> > We have a need for duplicated parsing of the RP_STATE_CAPS register (and
> > the setting of the associated fields). To reuse some code, we can
> > extract the function into a simple helper.
> > 
> > This patch also addresses the fact that we missed doing this for gen8,
> > something we should have done anyway.
> > 
> > This could be two patches, one to extract, and one to add gen8, but it's
> > trivial enough that I think one is fine. I will accept a request to
> > split it. Please notice the fix addressed by v2 below.
> > 
> > Valleyview is left untouched because it is different.
> > 
> > v2: Logically rebased on top of
> > commit dd0a1aa19bd3d7203e58157b84cea78bbac605ac
> > Author: Jeff McGee <jeff.mcgee@intel.com>
> > Date:   Tue Feb 4 11:32:31 2014 -0600
> > 
> >     drm/i915: Restore rps/rc6 on reset
> > 
> > Note with the above change the fix for gen8 is also handled (which was
> > not the case in Jeff's original patch).
> > 
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> 
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> 
> By setting max_freq_soft before querying overclocking frequencies, we
> force the user to have to manually raise the max freq through sysfs,
> right? Hasn't the user already explicitly asked for overclocking through
> the BIOS setting in the first place, so isn't that a needless burden
> upon the user?
> -Chris
> 

It's debatable, and if my memory serves, we've debated it before.
Overclocking has a range. BIOS enables the user to select a value within
that range. Selecting the highest possible value for the user is a
policy decision (IMO). If BIOS/punit wanted to control this, it should
set rp0 equal to the max overclock frequency, and not even bother
letting the driver deal with it. By not selecting anything, we're not
making any decision.

Daniel, please notice he did put the r-b tag on it.

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0
  2014-03-22 18:42           ` Ben Widawsky
@ 2014-03-22 21:06             ` Chris Wilson
  2014-03-24 19:27               ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2014-03-22 21:06 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: Intel GFX

On Sat, Mar 22, 2014 at 11:42:17AM -0700, Ben Widawsky wrote:
> On Thu, Mar 20, 2014 at 07:24:38AM +0000, Chris Wilson wrote:
> > On Wed, Mar 19, 2014 at 06:31:14PM -0700, Ben Widawsky wrote:
> > > Programming it outside of the rp0-rp1 range is considered a programming
> > > error. Since we do not know that the previous value would actually be in
> > > the range, program something we've read from the hardware, and therefore
> > > know will work.
> > > 
> > > This is potentially an issue for platforms whose ranges are outside the
> > > norms given in the programming guide (ie. early silicon)
> > > 
> > > v2: Use RP1 instead of RPn
> > > 
> > > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > 
> > Do you have a reference for GEN6_RC_VIDEO_FREQ? I still have no idea
> > what that controls, nor its valid range.
> > -Chris
> > 
> 
> I have no reference for the video freq other than the brief mention in
> the programming guide, and know nothing more than you do about it. It's
> there because the original spec I had said to program it to 600MHz. The
> reason for /this/ patch was that I noticed the default values happened
> to be a *really* close to our max freq. and figured someone, somewhere
> might get a part whose lower, or upper bound precludes setting the
> constant provided in the programming guide.
> 
> Interestingly, the programming guide has been updated since I originally
> wrote this patch to clearly indicate both of these registers need to be
> programmed between Rp1-Rp0. So I guess that means that Rp1-Rp0 is the
> valid range. Therefore, I think we should either proceed with this
> patch, or create a new patch to avoid writing it at all. The current
> code seems like the worst solution of all.
> 
> If you want to argue we can drop the write to GEN6_RPNSWREQ since we do
> the correct thing after step 6:
> gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
> 
> I wouldn't be too opposed. I was just trying to follow the spec as
> closely as possible, and it says to write the register value in this
> sequence, so I did.

Let's mark that as

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

and move on. Though I may double check to see if I can find some
information on the video frequency.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 12/12] drm/i915/bdw: Enable RC6
  2014-03-20  1:31       ` [PATCH 12/12] drm/i915/bdw: Enable RC6 Ben Widawsky
@ 2014-03-24 10:27         ` Deepak S
  0 siblings, 0 replies; 97+ messages in thread
From: Deepak S @ 2014-03-24 10:27 UTC (permalink / raw)
  To: intel-gfx

On Thursday 20 March 2014 07:01 AM, Ben Widawsky wrote:
> It is tested and looking fairly stable now, so turn it on. It wasn't
> intentionally turned off originally :P
>
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>   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 38e4d60..8e98042 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -4518,7 +4518,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
>   		ironlake_enable_drps(dev);
>   		ironlake_enable_rc6(dev);
>   		intel_init_emon(dev);
> -	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
> +	} else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
>   		if (IS_VALLEYVIEW(dev))
>   			valleyview_setup_pctx(dev);
>   		/*

Reviewed-by: Deepak S <deepak.s@linux.intel.com>

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

* Re: [PATCH 02/12] drm/i915: Fix coding style for RPS
  2014-03-20  1:31       ` [PATCH 02/12] drm/i915: Fix coding style for RPS Ben Widawsky
  2014-03-20  7:31         ` Chris Wilson
@ 2014-03-24 10:30         ` Deepak S
  1 sibling, 0 replies; 97+ messages in thread
From: Deepak S @ 2014-03-24 10:30 UTC (permalink / raw)
  To: intel-gfx

On Thursday 20 March 2014 07:01 AM, Ben Widawsky wrote:
> Introduced:
> commit b8a5ff8d7c676a04e0da5ec16bb068dd39459042
> Author: Jeff McGee <jeff.mcgee@intel.com>
> Date:   Tue Feb 4 11:37:01 2014 -0600
>
>      drm/i915: Update rps interrupt limits
>
> Cc: Jeff McGee <jeff.mcgee@intel.com>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>   drivers/gpu/drm/i915/i915_sysfs.c | 20 ++++++++++----------
>   1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index 0c741f4..e9ffefb 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -356,12 +356,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>   			valleyview_set_rps(dev, val);
>   		else
>   			gen6_set_rps(dev, val);
> -	}
> -	else if (!IS_VALLEYVIEW(dev))
> -		/* We still need gen6_set_rps to process the new max_delay
> -		   and update the interrupt limits even though frequency
> -		   request is unchanged. */
> +	} else if (!IS_VALLEYVIEW(dev)) {
> +		/* We still need gen6_set_rps to process the new max_delay and
> +		 * update the interrupt limits even though frequency request is
> +		 * unchanged. */
>   		gen6_set_rps(dev, dev_priv->rps.cur_delay);
> +	}
>   
>   	mutex_unlock(&dev_priv->rps.hw_lock);
>   
> @@ -430,12 +430,12 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
>   			valleyview_set_rps(dev, val);
>   		else
>   			gen6_set_rps(dev, val);
> -	}
> -	else if (!IS_VALLEYVIEW(dev))
> -		/* We still need gen6_set_rps to process the new min_delay
> -		   and update the interrupt limits even though frequency
> -		   request is unchanged. */
> +	} else if (!IS_VALLEYVIEW(dev)) {
> +		/* We still need gen6_set_rps to process the new min_delay and
> +		 * update the interrupt limits even though frequency request is
> +		 * unchanged. */
>   		gen6_set_rps(dev, dev_priv->rps.cur_delay);
> +	}
>   
>   	mutex_unlock(&dev_priv->rps.hw_lock);
>   

Reviewed-by: Deepak S <deepak.s@linux.intel.com>

Reviewed-by: Deepak S <deepak.s@linux.intel.com>

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

* Re: [PATCH 03/12] drm/i915: Store the HW min frequency as min_freq
  2014-03-20  1:31       ` [PATCH 03/12] drm/i915: Store the HW min frequency as min_freq Ben Widawsky
  2014-03-20  7:29         ` Chris Wilson
@ 2014-03-24 10:31         ` Deepak S
  1 sibling, 0 replies; 97+ messages in thread
From: Deepak S @ 2014-03-24 10:31 UTC (permalink / raw)
  To: Ben Widawsky, Intel GFX

On Thursday 20 March 2014 07:01 AM, Ben Widawsky wrote:
> this leaves a temporarily awkward min_delay (the soft limit) with the
> new min_freq (the hardware limit). It's fixed in the next patch.
>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>   drivers/gpu/drm/i915/i915_drv.h | 1 +
>   drivers/gpu/drm/i915/intel_pm.c | 2 +-
>   2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 9cd870f..241f5e1 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -987,6 +987,7 @@ struct intel_gen6_power_mgmt {
>   	u8 rp1_delay;
>   	u8 rp0_delay;
>   	u8 hw_max;
> +	u8 min_freq;
>   
>   	bool rp_up_masked;
>   	bool rp_down_masked;
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index dd3a121..dd631d1 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3354,7 +3354,7 @@ static void gen6_enable_rps(struct drm_device *dev)
>   
>   	/* In units of 50MHz */
>   	dev_priv->rps.hw_max = hw_max = rp_state_cap & 0xff;
> -	hw_min = (rp_state_cap >> 16) & 0xff;
> +	dev_priv->rps.min_freq = hw_min = (rp_state_cap >> 16) & 0xff;
>   	dev_priv->rps.rp1_delay = (rp_state_cap >>  8) & 0xff;
>   	dev_priv->rps.rp0_delay = (rp_state_cap >>  0) & 0xff;
>   	dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay;

Reviewed-by: Deepak S <deepak.s@linux.intel.com>

Reviewed-by: Deepak S <deepak.s@linux.intel.com>

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

* Re: [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0
  2014-03-22 21:06             ` Chris Wilson
@ 2014-03-24 19:27               ` Ben Widawsky
  0 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-03-24 19:27 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Intel GFX

On Sat, Mar 22, 2014 at 09:06:00PM +0000, Chris Wilson wrote:
> On Sat, Mar 22, 2014 at 11:42:17AM -0700, Ben Widawsky wrote:
> > On Thu, Mar 20, 2014 at 07:24:38AM +0000, Chris Wilson wrote:
> > > On Wed, Mar 19, 2014 at 06:31:14PM -0700, Ben Widawsky wrote:
> > > > Programming it outside of the rp0-rp1 range is considered a programming
> > > > error. Since we do not know that the previous value would actually be in
> > > > the range, program something we've read from the hardware, and therefore
> > > > know will work.
> > > > 
> > > > This is potentially an issue for platforms whose ranges are outside the
> > > > norms given in the programming guide (ie. early silicon)
> > > > 
> > > > v2: Use RP1 instead of RPn
> > > > 
> > > > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > > 
> > > Do you have a reference for GEN6_RC_VIDEO_FREQ? I still have no idea
> > > what that controls, nor its valid range.
> > > -Chris
> > > 
> > 
> > I have no reference for the video freq other than the brief mention in
> > the programming guide, and know nothing more than you do about it. It's
> > there because the original spec I had said to program it to 600MHz. The
> > reason for /this/ patch was that I noticed the default values happened
> > to be a *really* close to our max freq. and figured someone, somewhere
> > might get a part whose lower, or upper bound precludes setting the
> > constant provided in the programming guide.
> > 
> > Interestingly, the programming guide has been updated since I originally
> > wrote this patch to clearly indicate both of these registers need to be
> > programmed between Rp1-Rp0. So I guess that means that Rp1-Rp0 is the
> > valid range. Therefore, I think we should either proceed with this
> > patch, or create a new patch to avoid writing it at all. The current
> > code seems like the worst solution of all.
> > 
> > If you want to argue we can drop the write to GEN6_RPNSWREQ since we do
> > the correct thing after step 6:
> > gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
> > 
> > I wouldn't be too opposed. I was just trying to follow the spec as
> > closely as possible, and it says to write the register value in this
> > sequence, so I did.
> 
> Let's mark that as
> 
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> 
> and move on. Though I may double check to see if I can find some
> information on the video frequency.
> -Chris
> 

Danvet if/when this is merged, can you please reword the subject:
s/RP0/RP1

I'd say it was originally a typo, but that seems unlikely.


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

-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 10/12] drm/i915/bdw: Implement a basic PM interrupt handler
  2014-03-20  1:31       ` [PATCH 10/12] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
@ 2014-03-24 19:30         ` Ben Widawsky
  0 siblings, 0 replies; 97+ messages in thread
From: Ben Widawsky @ 2014-03-24 19:30 UTC (permalink / raw)
  To: Deepak S; +Cc: Intel GFX

Deepak, this patch can use review. If you have time, can you please take
a look.

There were some rebase conflicts from the last version, so please make
sure to recheck carefully (since I think you did look before).

Thanks.

On Wed, Mar 19, 2014 at 06:31:17PM -0700, Ben Widawsky wrote:
> Almost all of it is reusable from the existing code. The primary
> difference is we need to do even less in the interrupt handler, since
> interrupts are not shared in the same way.
> 
> The patch is mostly a copy-paste of the existing snb+ code, with updates
> to the relevant parts requiring changes to the interrupt handling. As
> such it /should/ be relatively trivial. It's highly likely that I missed
> some places where I need a gen8 version of the PM interrupts, but it has
> become invisible to me by now.
> 
> This patch could probably be split into adding the new functions,
> followed by actually handling the interrupts. Since the code is
> currently disabled (and broken) I think the patch stands better by
> itself.
> 
> v2: Move the commit about not touching the ringbuffer interrupt to the
> snb_* function where it belongs (Rodrigo)
> 
> v3: Rebased on Paulo's runtime PM changes
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/i915_irq.c  | 84 +++++++++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/i915_reg.h  |  1 +
>  drivers/gpu/drm/i915/intel_drv.h |  2 +
>  drivers/gpu/drm/i915/intel_pm.c  | 39 ++++++++++++++++++-
>  4 files changed, 119 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 4b4aeb3..2f9ec6e 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -175,6 +175,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> +	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
>  	new_val = dev_priv->pm_irq_mask;
>  	new_val &= ~interrupt_mask;
>  	new_val |= (~enabled_irq_mask & interrupt_mask);
> @@ -214,6 +215,53 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
>  	return true;
>  }
>  
> +/**
> +  * bdw_update_pm_irq - update GT interrupt 2
> +  * @dev_priv: driver private
> +  * @interrupt_mask: mask of interrupt bits to update
> +  * @enabled_irq_mask: mask of interrupt bits to enable
> +  *
> +  * Copied from the snb function, updated with relevant register offsets
> +  */
> +static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
> +			      uint32_t interrupt_mask,
> +			      uint32_t enabled_irq_mask)
> +{
> +	uint32_t new_val;
> +
> +	assert_spin_locked(&dev_priv->irq_lock);
> +
> +	if (dev_priv->pm.irqs_disabled) {
> +		WARN(1, "IRQs disabled\n");
> +		dev_priv->pm.regsave.gen6_pmimr &= ~interrupt_mask;
> +		dev_priv->pm.regsave.gen6_pmimr |= (~enabled_irq_mask &
> +						     interrupt_mask);
> +		return;
> +	}
> +
> +	new_val = dev_priv->pm_irq_mask;
> +	new_val &= ~interrupt_mask;
> +	new_val |= (~enabled_irq_mask & interrupt_mask);
> +
> +	if (new_val != dev_priv->pm_irq_mask) {
> +		dev_priv->pm_irq_mask = new_val;
> +		I915_WRITE(GEN8_GT_IMR(2), I915_READ(GEN8_GT_IMR(2)) |
> +					   dev_priv->pm_irq_mask);
> +		POSTING_READ(GEN8_GT_IMR(2));
> +	}
> +}
> +
> +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
> +{
> +	bdw_update_pm_irq(dev_priv, mask, mask);
> +}
> +
> +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
> +{
> +	bdw_update_pm_irq(dev_priv, mask, 0);
> +}
> +
> +
>  static bool cpt_can_enable_serr_int(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -1131,13 +1179,16 @@ static void gen6_pm_rps_work(struct work_struct *work)
>  	spin_lock_irq(&dev_priv->irq_lock);
>  	pm_iir = dev_priv->rps.pm_iir;
>  	dev_priv->rps.pm_iir = 0;
> -	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
> -	snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> +	if (IS_BROADWELL(dev_priv->dev))
> +		bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> +	else {
> +		snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> +		/* Make sure we didn't queue anything we're not going to
> +		 * process. */
> +		WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
> +	}
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
> -	/* Make sure we didn't queue anything we're not going to process. */
> -	WARN_ON(pm_iir & ~GEN6_PM_RPS_EVENTS);
> -
>  	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
>  		return;
>  
> @@ -1330,6 +1381,19 @@ static void snb_gt_irq_handler(struct drm_device *dev,
>  		ivybridge_parity_error_irq_handler(dev, gt_iir);
>  }
>  
> +static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
> +{
> +	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
> +		return;
> +
> +	spin_lock(&dev_priv->irq_lock);
> +	dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
> +	bdw_disable_pm_irq(dev_priv, pm_iir & GEN6_PM_RPS_EVENTS);
> +	spin_unlock(&dev_priv->irq_lock);
> +
> +	queue_work(dev_priv->wq, &dev_priv->rps.work);
> +}
> +
>  static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
>  				       struct drm_i915_private *dev_priv,
>  				       u32 master_ctl)
> @@ -1365,6 +1429,16 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
>  			DRM_ERROR("The master control interrupt lied (GT1)!\n");
>  	}
>  
> +	if (master_ctl & GEN8_GT_PM_IRQ) {
> +		tmp = I915_READ(GEN8_GT_IIR(2));
> +		if (tmp & GEN6_PM_RPS_EVENTS) {
> +			ret = IRQ_HANDLED;
> +			gen8_rps_irq_handler(dev_priv, tmp);
> +			I915_WRITE(GEN8_GT_IIR(1), tmp & GEN6_PM_RPS_EVENTS);
> +		} else
> +			DRM_ERROR("The master control interrupt lied (PM)!\n");
> +	}
> +
>  	if (master_ctl & GEN8_GT_VECS_IRQ) {
>  		tmp = I915_READ(GEN8_GT_IIR(3));
>  		if (tmp) {
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 6174fda..67952c7 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4086,6 +4086,7 @@ enum punit_power_well {
>  #define  GEN8_DE_PIPE_A_IRQ		(1<<16)
>  #define  GEN8_DE_PIPE_IRQ(pipe)		(1<<(16+pipe))
>  #define  GEN8_GT_VECS_IRQ		(1<<6)
> +#define  GEN8_GT_PM_IRQ			(1<<4)
>  #define  GEN8_GT_VCS2_IRQ		(1<<3)
>  #define  GEN8_GT_VCS1_IRQ		(1<<2)
>  #define  GEN8_GT_BCS_IRQ		(1<<1)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 60ffad3..fde5df7 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -623,6 +623,8 @@ void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void hsw_runtime_pm_disable_interrupts(struct drm_device *dev);
>  void hsw_runtime_pm_restore_interrupts(struct drm_device *dev);
> +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  
>  
>  /* intel_crt.c */
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 9486396..38e4d60 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3155,6 +3155,25 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
>  	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
>  }
>  
> +static void gen8_disable_rps_interrupts(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
> +	I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) &
> +				   ~GEN6_PM_RPS_EVENTS);
> +	/* Complete PM interrupt masking here doesn't race with the rps work
> +	 * item again unmasking PM interrupts because that is using a different
> +	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
> +	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
> +
> +	spin_lock_irq(&dev_priv->irq_lock);
> +	dev_priv->rps.pm_iir = 0;
> +	spin_unlock_irq(&dev_priv->irq_lock);
> +
> +	I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
> +}
> +
>  static void gen6_disable_rps_interrupts(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3180,7 +3199,10 @@ static void gen6_disable_rps(struct drm_device *dev)
>  	I915_WRITE(GEN6_RC_CONTROL, 0);
>  	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
>  
> -	gen6_disable_rps_interrupts(dev);
> +	if (IS_BROADWELL(dev))
> +		gen8_disable_rps_interrupts(dev);
> +	else
> +		gen6_disable_rps_interrupts(dev);
>  }
>  
>  static void valleyview_disable_rps(struct drm_device *dev)
> @@ -3225,6 +3247,19 @@ int intel_enable_rc6(const struct drm_device *dev)
>  	return INTEL_RC6_ENABLE;
>  }
>  
> +static void gen8_enable_rps_interrupts(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	spin_lock_irq(&dev_priv->irq_lock);
> +	WARN_ON(dev_priv->rps.pm_iir);
> +	bdw_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS);
> +	I915_WRITE(GEN8_GT_IIR(2), GEN6_PM_RPS_EVENTS);
> +	spin_unlock_irq(&dev_priv->irq_lock);
> +
> +	I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
> +}
> +
>  static void gen6_enable_rps_interrupts(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3339,7 +3374,7 @@ static void gen8_enable_rps(struct drm_device *dev)
>  
>  	gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
>  
> -	gen6_enable_rps_interrupts(dev);
> +	gen8_enable_rps_interrupts(dev);
>  
>  	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>  }
> -- 
> 1.9.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ben Widawsky, Intel Open Source Technology Center

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

end of thread, other threads:[~2014-03-24 19:31 UTC | newest]

Thread overview: 97+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-29  4:25 [PATCH 0/9] Broadwel RC6 & RPS Ben Widawsky
2014-01-29  4:25 ` [PATCH 1/9] drm/i915: Clarify RC6 enabling Ben Widawsky
2014-02-06 13:38   ` Rodrigo Vivi
     [not found]   ` <CAOh5HuUmDmAC9Nuu3DWYO2kU+Q5kyHyxSmF4rjADaY1iY6=RaQ@mail.gmail.com>
2014-02-07  5:30     ` S, Deepak
2014-02-18  3:01   ` [PATCH 00/11] [v2] BDW RPS + RC6 + rps fixlets Ben Widawsky
2014-02-18  3:01     ` [PATCH 01/11] drm/i915: Reorganize the overclock code Ben Widawsky
2014-02-18  3:01     ` [PATCH 02/11] drm/i915: Fix coding style for RPS Ben Widawsky
2014-02-18  3:01     ` [PATCH 03/11] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
2014-02-18 19:03       ` [PATCH 03/11] [v2] " Ben Widawsky
2014-02-22 13:37       ` [PATCH 03/11] " Chris Wilson
2014-02-22 19:34         ` Ben Widawsky
2014-02-22 19:37           ` Chris Wilson
2014-02-22 19:40             ` Ben Widawsky
2014-02-22 20:08               ` Chris Wilson
2014-02-25  0:54                 ` Ben Widawsky
2014-02-22 19:38           ` Ben Widawsky
2014-02-22 20:14             ` Chris Wilson
2014-03-19  1:27         ` Ben Widawsky
2014-03-19  2:38           ` Ben Widawsky
2014-03-19  6:49             ` Chris Wilson
2014-02-18  3:01     ` [PATCH 04/11] drm/i915: Remove extraneous MMIO for RPS Ben Widawsky
2014-02-18  3:01     ` [PATCH 05/11] drm/i915: remove rps local variables Ben Widawsky
2014-02-18  3:01     ` [PATCH 06/11] drm/i915/bdw: Set initial rps freq to nominal Ben Widawsky
2014-02-18  3:01     ` [PATCH 07/11] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
2014-02-18  3:01     ` [PATCH 08/11] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
2014-02-18  3:01     ` [PATCH 09/11] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
2014-02-18  3:01     ` [PATCH 10/11] drm/i915/bdw: Enable RC6 Ben Widawsky
2014-02-18  3:01     ` [PATCH 11/11] drm/i915/bdw: Ensure a context is loaded before RC6 Ben Widawsky
2014-02-18  3:03       ` [PATCH 11/11] [v2] " Ben Widawsky
2014-02-18  3:56         ` [PATCH 11/11] [v3] " Ben Widawsky
2014-02-20  6:27           ` [PATCH 11/11] [v4] " Ben Widawsky
2014-03-04 14:30             ` Daniel Vetter
2014-03-20  0:41               ` Ben Widawsky
2014-03-20 13:42                 ` Daniel Vetter
2014-03-20 17:30                   ` Jesse Barnes
2014-03-20 20:12                     ` Jesse Barnes
2014-03-20  1:31     ` [PATCH 00/12] [v3] BDW RPS + RC6 + rps fixlets Ben Widawsky
2014-03-20  1:31       ` [PATCH 01/12] drm/i915: Reorganize the overclock code Ben Widawsky
2014-03-20  7:23         ` Chris Wilson
2014-03-20  1:31       ` [PATCH 02/12] drm/i915: Fix coding style for RPS Ben Widawsky
2014-03-20  7:31         ` Chris Wilson
2014-03-24 10:30         ` Deepak S
2014-03-20  1:31       ` [PATCH 03/12] drm/i915: Store the HW min frequency as min_freq Ben Widawsky
2014-03-20  7:29         ` Chris Wilson
2014-03-24 10:31         ` Deepak S
2014-03-20  1:31       ` [PATCH 04/12] drm/i915: Rename and comment all the RPS *stuff* Ben Widawsky
2014-03-20  7:01         ` Chris Wilson
2014-03-20  1:31       ` [PATCH 05/12] drm/i915: Remove extraneous MMIO for RPS Ben Widawsky
2014-03-20  7:30         ` Chris Wilson
2014-03-20  1:31       ` [PATCH 06/12] drm/i915: remove rps local variables Ben Widawsky
2014-03-20  7:30         ` Chris Wilson
2014-03-20 13:46           ` Daniel Vetter
2014-03-20  1:31       ` [PATCH 07/12] drm/i915/bdw: Set initial rps freq to RP0 Ben Widawsky
2014-03-20  7:24         ` Chris Wilson
2014-03-22 18:42           ` Ben Widawsky
2014-03-22 21:06             ` Chris Wilson
2014-03-24 19:27               ` Ben Widawsky
2014-03-20  1:31       ` [PATCH 08/12] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
2014-03-20  7:28         ` Chris Wilson
2014-03-22 18:46           ` Ben Widawsky
2014-03-20  1:31       ` [PATCH 09/12] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
2014-03-20  1:31       ` [PATCH 10/12] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
2014-03-24 19:30         ` Ben Widawsky
2014-03-20  1:31       ` [PATCH 11/12] drm/i915/bdw: Ensure a context is loaded before RC6 Ben Widawsky
2014-03-20  7:35         ` Chris Wilson
2014-03-20  1:31       ` [PATCH 12/12] drm/i915/bdw: Enable RC6 Ben Widawsky
2014-03-24 10:27         ` Deepak S
2014-01-29  4:25 ` [PATCH 2/9] drm/i915: Stop pretending VLV has rc6+ Ben Widawsky
2014-02-06 13:39   ` Rodrigo Vivi
     [not found]   ` <CAOh5HuXxFqRixpPSeOpi=1t2sL=sVfmjdMR445dEQBozg1Z43w@mail.gmail.com>
2014-02-07  5:42     ` S, Deepak
2014-01-29  4:25 ` [PATCH 3/9] drm/i915: Just print rc6 facts Ben Widawsky
2014-02-06 13:41   ` Rodrigo Vivi
     [not found]   ` <CAOh5HuW+_5n=zfDSf_F1aT+v7xzdm_GwUxKC5t8g6_LVCX6X_g@mail.gmail.com>
2014-02-07  5:44     ` S, Deepak
2014-01-29  4:25 ` [PATCH 4/9] drm/i915/bdw: Use centralized rc6 info print Ben Widawsky
2014-02-06 13:42   ` Rodrigo Vivi
2014-02-11 16:12     ` Daniel Vetter
2014-02-14 20:34       ` Ben Widawsky
2014-02-14 20:41         ` Chris Wilson
2014-02-17 19:41           ` Ben Widawsky
     [not found]   ` <CAOh5HuVu0vvQNFKt2FhVf9CrXQa47WAfaqWP2EHp=mBMgExTkQ@mail.gmail.com>
2014-02-07  5:46     ` S, Deepak
2014-01-29  4:25 ` [PATCH 5/9] drm/i915/bdw: Extract rp_state_caps logic Ben Widawsky
2014-01-29  4:25 ` [PATCH 5/9] drm/i915/bdw: Set rp_state_caps Ben Widawsky
2014-02-06 13:45   ` Rodrigo Vivi
     [not found]   ` <CAOh5HuUqCUM-2-yxCbPcCZ53yTxN+8Q5+syiAXqa86Vp47T70A@mail.gmail.com>
2014-02-07  6:10     ` S, Deepak
2014-01-29  4:25 ` [PATCH 6/9] drm/i915/bdw: Set initial rps freq to nominal Ben Widawsky
2014-01-29  4:25 ` [PATCH 7/9] drm/i915/bdw: RPS frequency bits are the same as HSW Ben Widawsky
2014-02-06 13:52   ` Rodrigo Vivi
     [not found]   ` <CAOh5HuU8bnYppf7D5k39QuuDkbHCUVznuVHzvd2dW1mDN0GpBA@mail.gmail.com>
2014-02-07  6:25     ` S, Deepak
2014-01-29  4:25 ` [PATCH 8/9] drm/i915/bdw: Implement a basic PM interrupt handler Ben Widawsky
2014-02-06 14:15   ` Rodrigo Vivi
2014-02-17 20:01     ` Ben Widawsky
     [not found]   ` <CAOh5HuXYmUmGM2tDGO6KCT9Q1V6znbAwQf5OoC27++078bvfRg@mail.gmail.com>
2014-02-07  6:43     ` S, Deepak
2014-01-29  4:25 ` [PATCH 9/9] drm/i915/bdw: Enable RC6 Ben Widawsky
2014-02-06 13:54   ` Rodrigo Vivi
2014-02-17 20:04     ` Ben Widawsky
2014-02-17 20:07       ` Ben Widawsky
     [not found]   ` <CAOh5HuW-f4xdojasEP3wkSoVH3W1NJNdPACafgnPfVujFe4fjw@mail.gmail.com>
2014-02-07  6:47     ` S, Deepak

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.