Skip to contentSkip to conversation

Enable RC6/Turbo on CHV

PATCH In review [email protected] 4 participants 26 messages May 5, 2014 – May 16, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Enable RC6/Turbo on CHV

From: Deepak S <[email protected]>

Squashed some of the patches and created a new patch series. Addressed review comments on most of the patches.

Ben Widawsky (1):
drm/i915/bdw: Implement a basic PM interrupt handler

Deepak S (7):
drm/i915: Enable PM Interrupts target via Display Interface. drm/i915/chv: Enable Render Standby (RC6) for Cherryview drm/i915/chv: Added CHV specific register read and write drm/i915/chv: Streamline CHV forcewake stuff drm/i915/chv: Enable RPS (Turbo) for Cherryview drm/i915/chv: Added CHV specific DDR fetch into init_clock_gating drm/i915/chv: Freq(opcode) request for CHV.

Ville Syrjälä (2):
drm/i915/chv: CHV doesn't need WaRsForcewakeWaitTC0 drm/i915/chv: Skip gen6_gt_check_fifodbg() on CHV

 drivers/gpu/drm/i915/i915_drv.h       |   2 +
 drivers/gpu/drm/i915/i915_irq.c       |  84 ++++++++++-
 drivers/gpu/drm/i915/i915_reg.h       |  17 +++
 drivers/gpu/drm/i915/intel_drv.h      |   2 +
 drivers/gpu/drm/i915/intel_pm.c       | 259 ++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_sideband.c |  15 ++
 drivers/gpu/drm/i915/intel_uncore.c   | 146 ++++++++++++++++---
 7 files changed, 491 insertions(+), 34 deletions(-)
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#1 lore raw

PATCH 1/10 drm/i915/bdw: Implement a basic PM interrupt handler

From: Ben Widawsky <[email protected]>

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

v4: Not well validated, but rebase on
commit 730488b2eddded4497f63f70867b1256cd9e117c

Author: Paulo Zanoni <[email protected]>
Date:   Fri Mar 7 20:12:32 2014 -0300
    drm/i915: kill dev_priv->pm.regsave

v5: Rebased on latest code base. (Deepak)

v6: Remove conflict markers, Unnecessary empty line and use right IIR interrupt (Ville)

---
 drivers/gpu/drm/i915/i915_irq.c  | 75 ++++++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_drv.h |  2 ++
 drivers/gpu/drm/i915/intel_pm.c  | 38 ++++++++++++++++++--
 4 files changed, 112 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +73 -2
index 2d76183..6af51ad 100644
@@ -248,6 +248,49 @@ 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");
+		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;
@@ -1098,8 +1141,12 @@ 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, dev_priv->pm_rps_events);
+	if (IS_BROADWELL(dev_priv->dev))
+		bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+	else {
+		/* Make sure not to corrupt PMIMR state used by ringbuffer */
+		snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+	}
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	/* Make sure we didn't queue anything we're not going to process. */
@@ -1296,6 +1343,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 & dev_priv->pm_rps_events) == 0)
+		return;
+
+	spin_lock(&dev_priv->irq_lock);
+	dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
+	bdw_disable_pm_irq(dev_priv, pm_iir & dev_priv->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)
@@ -1334,6 +1394,17 @@ 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 & dev_priv->pm_rps_events) {
+			ret = IRQ_HANDLED;
+			gen8_rps_irq_handler(dev_priv, tmp);
+			I915_WRITE(GEN8_GT_IIR(2),
+				   tmp & dev_priv->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) {
drivers/gpu/drm/i915/i915_reg.h +1 -0
index 0eff337..ca4f8b9 100644
@@ -4194,6 +4194,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)
drivers/gpu/drm/i915/intel_drv.h +2 -0
index d8b540b..d560a9b 100644
@@ -653,6 +653,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 intel_runtime_pm_disable_interrupts(struct drm_device *dev);
 void intel_runtime_pm_restore_interrupts(struct drm_device *dev);
 int intel_get_crtc_scanline(struct intel_crtc *crtc);
drivers/gpu/drm/i915/intel_pm.c +36 -2
index 834c49c..0e69c97 100644
@@ -3246,6 +3246,26 @@ 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)) &
+				   ~dev_priv->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 (GEN8_GT_IMR(2)) to mask PM interrupts. The only risk is in
+	 * leaving stale bits in GEN8_GT_IIR(2) and GEN8_GT_IMR(2) which
+	 * gen8_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), dev_priv->pm_rps_events);
+}
+
 static void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3272,7 +3292,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)
@@ -3344,6 +3367,17 @@ int intel_enable_rc6(const struct drm_device *dev)
 	return i915.enable_rc6;
 }
 
+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, dev_priv->pm_rps_events);
+	I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events);
+	spin_unlock_irq(&dev_priv->irq_lock);
+}
+
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3446,7 +3480,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);
 }
Signature · 1 line
1.9.1
#2 lore raw

Re: [PATCH 01/10] drm/i915/bdw: Implement a basic PM interrupt handler

Quoted 61 lines · On Mon, May 05, 2014 at 06:17:30PM +0530, [email protected] wrote:

From: Ben Widawsky <[email protected]>

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

v4: Not well validated, but rebase on
commit 730488b2eddded4497f63f70867b1256cd9e117c

Author: Paulo Zanoni <[email protected]>
Date:   Fri Mar 7 20:12:32 2014 -0300
    drm/i915: kill dev_priv->pm.regsave

v5: Rebased on latest code base. (Deepak)

v6: Remove conflict markers, Unnecessary empty line and use right IIR interrupt (Ville)

---
 drivers/gpu/drm/i915/i915_irq.c  | 75 ++++++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_drv.h |  2 ++
 drivers/gpu/drm/i915/intel_pm.c  | 38 ++++++++++++++++++--
 4 files changed, 112 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +10 -0
index 2d76183..6af51ad 100644
@@ -248,6 +248,49 @@ 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,

drivers/gpu/drm/i915/i915_irq.c static bool ivb_can_enable_err_int(struct drm_device *dev) · line 270

Quoted 10 lines
drivers/gpu/drm/i915/i915_irq.c +10 -0
+			      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");
+		return;
+	}

Could be just 'if (WARN...' just like in the snb function.

drivers/gpu/drm/i915/i915_irq.c static bool ivb_can_enable_err_int(struct drm_device *dev) · line 279

Quoted 9 lines
drivers/gpu/drm/i915/i915_irq.c +9 -0
+
+	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);

I just realized that this doesn't actually clear the old bits. I think we should just kill the RMW here and mandate that all users of GT_IMR(2) need to use this function.

Also you're forgetting to initialize pm_irq_mask. I guess it should be initialized in gen8_gt_irq_postinstall() to match the gen6 code.

Quoted 172 lines
drivers/gpu/drm/i915/i915_irq.c +44 -2
+		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;
@@ -1098,8 +1141,12 @@ 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, dev_priv->pm_rps_events);
+	if (IS_BROADWELL(dev_priv->dev))
+		bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+	else {
+		/* Make sure not to corrupt PMIMR state used by ringbuffer */
+		snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+	}
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	/* Make sure we didn't queue anything we're not going to process. */
@@ -1296,6 +1343,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 & dev_priv->pm_rps_events) == 0)
+		return;
+
+	spin_lock(&dev_priv->irq_lock);
+	dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
+	bdw_disable_pm_irq(dev_priv, pm_iir & dev_priv->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)
@@ -1334,6 +1394,17 @@ 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 & dev_priv->pm_rps_events) {
+			ret = IRQ_HANDLED;
+			gen8_rps_irq_handler(dev_priv, tmp);
+			I915_WRITE(GEN8_GT_IIR(2),
+				   tmp & dev_priv->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) {
drivers/gpu/drm/i915/i915_reg.h +1 -0
index 0eff337..ca4f8b9 100644
@@ -4194,6 +4194,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)
drivers/gpu/drm/i915/intel_drv.h +2 -0
index d8b540b..d560a9b 100644
@@ -653,6 +653,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 intel_runtime_pm_disable_interrupts(struct drm_device *dev);
 void intel_runtime_pm_restore_interrupts(struct drm_device *dev);
 int intel_get_crtc_scanline(struct intel_crtc *crtc);
drivers/gpu/drm/i915/intel_pm.c +36 -2
index 834c49c..0e69c97 100644
@@ -3246,6 +3246,26 @@ 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)) &
+				   ~dev_priv->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 (GEN8_GT_IMR(2)) to mask PM interrupts. The only risk is in
+	 * leaving stale bits in GEN8_GT_IIR(2) and GEN8_GT_IMR(2) which
+	 * gen8_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), dev_priv->pm_rps_events);
+}
+
 static void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3272,7 +3292,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)
@@ -3344,6 +3367,17 @@ int intel_enable_rc6(const struct drm_device *dev)
 	return i915.enable_rc6;
 }
 
+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, dev_priv->pm_rps_events);
+	I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events);
+	spin_unlock_irq(&dev_priv->irq_lock);
+}
+
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3446,7 +3480,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);
 }
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 2 lines
Ville Syrjälä
Intel OTC
#3 lore raw

PATCH 2/10 drm/i915: Enable PM Interrupts target via Display Interface.

In reply to [email protected]

From: Deepak S <[email protected]>

In BDW, Apart from unmasking up/down threshold interrupts. we need to umask bit 32 of PM_INTRMASK to route interrupts to target via Display Interface.

v2: Add (1<<31) mask (Ville)

---
 drivers/gpu/drm/i915/i915_reg.h | 1 +
 drivers/gpu/drm/i915/intel_pm.c | 2 ++
 2 files changed, 3 insertions(+)
drivers/gpu/drm/i915/i915_reg.h +1 -0
index ca4f8b9..c850254 100644
@@ -5112,6 +5112,7 @@ enum punit_power_well {
 #define GEN6_RC6p_THRESHOLD			0xA0BC
 #define GEN6_RC6pp_THRESHOLD			0xA0C0
 #define GEN6_PMINTRMSK				0xA168
+#define GEN8_PMINTR_REDIRECT_TO_NON_DISP	(1<<31)
 
 #define GEN6_PMISR				0x44020
 #define GEN6_PMIMR				0x44024 /* rps_lock */
drivers/gpu/drm/i915/intel_pm.c +2 -0
index 0e69c97..ebb5c88 100644
@@ -3114,6 +3114,8 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
 	if (INTEL_INFO(dev_priv->dev)->gen <= 7 && !IS_HASWELL(dev_priv->dev))
 		mask |= GEN6_PM_RP_UP_EI_EXPIRED;
 
+	mask |= GEN8_PMINTR_REDIRECT_TO_NON_DISP;
+
 	return ~mask;
 }
 
Signature · 1 line
1.9.1
#4 lore raw

Re: [PATCH 02/10] drm/i915: Enable PM Interrupts target via Display Interface.

Quoted 31 lines · On Mon, May 05, 2014 at 06:17:31PM +0530, [email protected] wrote:

From: Deepak S <[email protected]>

In BDW, Apart from unmasking up/down threshold interrupts. we need to umask bit 32 of PM_INTRMASK to route interrupts to target via Display Interface.

v2: Add (1<<31) mask (Ville)

---
 drivers/gpu/drm/i915/i915_reg.h | 1 +
 drivers/gpu/drm/i915/intel_pm.c | 2 ++
 2 files changed, 3 insertions(+)
drivers/gpu/drm/i915/i915_reg.h +1 -0
index ca4f8b9..c850254 100644
@@ -5112,6 +5112,7 @@ enum punit_power_well {
 #define GEN6_RC6p_THRESHOLD			0xA0BC
 #define GEN6_RC6pp_THRESHOLD			0xA0C0
 #define GEN6_PMINTRMSK				0xA168
+#define GEN8_PMINTR_REDIRECT_TO_NON_DISP	(1<<31)
 
 #define GEN6_PMISR				0x44020
 #define GEN6_PMIMR				0x44024 /* rps_lock */
drivers/gpu/drm/i915/intel_pm.c +0 -0
index 0e69c97..ebb5c88 100644

drivers/gpu/drm/i915/intel_pm.c static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val) · line 3118

Quoted 5 lines
drivers/gpu/drm/i915/intel_pm.c +2 -0
@@ -3114,6 +3114,8 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
 	if (INTEL_INFO(dev_priv->dev)->gen <= 7 && !IS_HASWELL(dev_priv->dev))
 		mask |= GEN6_PM_RP_UP_EI_EXPIRED;
 
+	mask |= GEN8_PMINTR_REDIRECT_TO_NON_DISP;
+

Didn't Ben want a gen check here?

Quoted 10 lines
drivers/gpu/drm/i915/intel_pm.c +0 -0
 	return ~mask;
 }
 
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 2 lines
Ville Syrjälä
Intel OTC
#5 lore raw

PATCH v3 1/1 drm/i915: Enable PM Interrupts target via Display Interface.

In reply to [email protected]

From: Deepak S <[email protected]>

In BDW, Apart from unmasking up/down threshold interrupts. we need to umask bit 32 of PM_INTRMASK to route interrupts to target via Display Interface.

v2: Add (1<<31) mask (Ville)

v3: Add Gen check for the mask (ville)

---
 drivers/gpu/drm/i915/i915_reg.h | 1 +
 drivers/gpu/drm/i915/intel_pm.c | 3 +++
 2 files changed, 4 insertions(+)
drivers/gpu/drm/i915/i915_reg.h +1 -0
index ca4f8b9..c850254 100644
@@ -5112,6 +5112,7 @@ enum punit_power_well {
 #define GEN6_RC6p_THRESHOLD			0xA0BC
 #define GEN6_RC6pp_THRESHOLD			0xA0C0
 #define GEN6_PMINTRMSK				0xA168
+#define GEN8_PMINTR_REDIRECT_TO_NON_DISP	(1<<31)
 
 #define GEN6_PMISR				0x44020
 #define GEN6_PMIMR				0x44024 /* rps_lock */
drivers/gpu/drm/i915/intel_pm.c +3 -0
index 0e69c97..270b659 100644
@@ -3114,6 +3114,9 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
 	if (INTEL_INFO(dev_priv->dev)->gen <= 7 && !IS_HASWELL(dev_priv->dev))
 		mask |= GEN6_PM_RP_UP_EI_EXPIRED;
 
+	if (IS_GEN8(dev_priv->dev))
+		mask |= GEN8_PMINTR_REDIRECT_TO_NON_DISP;
+
 	return ~mask;
 }
 
Signature · 1 line
1.9.1
Reviewed-by on v3 1/1
#6 lore raw

Re: [PATCH v3] drm/i915: Enable PM Interrupts target via Display Interface.

Quoted 11 lines · On Wed, May 14, 2014 at 09:07:53PM +0530, [email protected] wrote:

From: Deepak S <[email protected]>

In BDW, Apart from unmasking up/down threshold interrupts. we need to umask bit 32 of PM_INTRMASK to route interrupts to target via Display Interface.

v2: Add (1<<31) mask (Ville)

v3: Add Gen check for the mask (ville)

Quoted 38 lines
---
 drivers/gpu/drm/i915/i915_reg.h | 1 +
 drivers/gpu/drm/i915/intel_pm.c | 3 +++
 2 files changed, 4 insertions(+)
drivers/gpu/drm/i915/i915_reg.h +1 -0
index ca4f8b9..c850254 100644
@@ -5112,6 +5112,7 @@ enum punit_power_well {
 #define GEN6_RC6p_THRESHOLD			0xA0BC
 #define GEN6_RC6pp_THRESHOLD			0xA0C0
 #define GEN6_PMINTRMSK				0xA168
+#define GEN8_PMINTR_REDIRECT_TO_NON_DISP	(1<<31)
 
 #define GEN6_PMISR				0x44020
 #define GEN6_PMIMR				0x44024 /* rps_lock */
drivers/gpu/drm/i915/intel_pm.c +3 -0
index 0e69c97..270b659 100644
@@ -3114,6 +3114,9 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
 	if (INTEL_INFO(dev_priv->dev)->gen <= 7 && !IS_HASWELL(dev_priv->dev))
 		mask |= GEN6_PM_RP_UP_EI_EXPIRED;
 
+	if (IS_GEN8(dev_priv->dev))
+		mask |= GEN8_PMINTR_REDIRECT_TO_NON_DISP;
+
 	return ~mask;
 }
 
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 2 lines
Ville Syrjälä
Intel OTC
#7 lore raw

PATCH 3/10 drm/i915/chv: Enable Render Standby (RC6) for Cherryview

In reply to [email protected]

From: Deepak S <[email protected]>

v2: Configure PCBR if BIOS fails allocate pcbr (deepak)

v3: Fix PCBR condition check during CHV RC6 Enable flag set

v4: Fixup PCBR comment msg. (Chris)
Rebase against latest code (Deak)
Fixup Spurious hunk (Ben)

---
 drivers/gpu/drm/i915/i915_reg.h |   2 +
 drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +2 -0
index c850254..b4074fd 100644
@@ -962,6 +962,8 @@ enum punit_power_well {
 #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
 #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
 #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
 #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
 #define EIR		0x020b0
 #define EMR		0x020b4
drivers/gpu/drm/i915/intel_pm.c +109 -6

170 lines not on this page · raw message

Signature · 1 line
1.9.1
#8 lore raw

Re: [PATCH 03/10] drm/i915/chv: Enable Render Standby (RC6) for Cherryview

Hi Deepak,

Quoted 63 lines · [email protected] writes:

From: Deepak S <[email protected]>

v2: Configure PCBR if BIOS fails allocate pcbr (deepak)

v3: Fix PCBR condition check during CHV RC6 Enable flag set

v4: Fixup PCBR comment msg. (Chris)
Rebase against latest code (Deak)
Fixup Spurious hunk (Ben)

---
 drivers/gpu/drm/i915/i915_reg.h |   2 +
 drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +2 -0
index c850254..b4074fd 100644
@@ -962,6 +962,8 @@ enum punit_power_well {
 #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
 #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
 #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
 #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
 #define EIR		0x020b0
 #define EMR		0x020b4
drivers/gpu/drm/i915/intel_pm.c +18 -0
index ebb5c88..f0359b6 100644
@@ -3300,6 +3300,13 @@ static void gen6_disable_rps(struct drm_device *dev)
 		gen6_disable_rps_interrupts(dev);
 }
 
+static void cherryview_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RC_CONTROL, 0);
+}
+
 static void valleyview_disable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3722,6 +3729,33 @@ static void valleyview_check_pctx(struct drm_i915_private *dev_priv)
 			     dev_priv->vlv_pctx->stolen->start);
 }
 
+
+/* Check that the pcbr address is not empty. */
+static void cherryview_check_pctx(struct drm_i915_private *dev_priv)
+{
+	unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
+
+	WARN_ON((pctx_addr >> VLV_PCBR_ADDR_SHIFT) == 0);
+}
+
+static void cherryview_setup_pctx(struct drm_device *dev)
+{

drivers/gpu/drm/i915/intel_pm.c static void valleyview_check_pctx(struct drm_i915_private *dev_priv) · line 3752

Quoted 10 lines
drivers/gpu/drm/i915/intel_pm.c +10 -0
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long pctx_paddr;
+	struct i915_gtt *gtt = &dev_priv->gtt;
+	u32 pcbr;
+	int pctx_size = 32*1024;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	pcbr = I915_READ(VLV_PCBR);
+	if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {

I admit that address zero locked by bios is prolly in realms of paranoia. But I would still omit shift here to get lock bit taken into consideration.

drivers/gpu/drm/i915/intel_pm.c static void valleyview_check_pctx(struct drm_i915_private *dev_priv) · line 3755

Quoted 3 lines
drivers/gpu/drm/i915/intel_pm.c +3 -0
+		pctx_paddr = (dev_priv->mm.stolen_base +
+			      (gtt->stolen_size - pctx_size));
+		I915_WRITE(VLV_PCBR, pctx_paddr);

In here tho I would mask the low bits out, just to be on the safe side. If we get off by one on stolen calculation we end up writing the lock bit.

I am thinking that we should just sanity check that bios
has set this up and that it seems to be in correct place. If not, spit a warning and leave rc6 disabled.

The BIOS should have setup everything for us. Why do we need this PCBR setup?

Quoted 32 lines
drivers/gpu/drm/i915/intel_pm.c +20 -0
+	}
+}
+
 static void valleyview_setup_pctx(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3811,11 +3845,72 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
 	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
+static void cherryview_init_gt_powersave(struct drm_device *dev)
+{
+	cherryview_setup_pctx(dev);
+}
+
 static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
 {
 	valleyview_cleanup_pctx(dev);
 }
 
+static void cherryview_enable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	u32 gtfifodbg, rc6_mode = 0, pcbr;
+	int i;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	gtfifodbg = I915_READ(GTFIFODBG);
+	if (gtfifodbg) {
+		DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev) · line 3879

Quoted 10 lines
drivers/gpu/drm/i915/intel_pm.c +10 -0
+				 gtfifodbg);
+		I915_WRITE(GTFIFODBG, gtfifodbg);
+	}
+
+	cherryview_check_pctx(dev_priv);
+
+	/* 1a & 1b: Get forcewake during program sequence. Although the driver
+	 * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+

I915_WRITE(GEN6_RC_CONTROL, 0);

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev) · line 3887

Quoted 8 lines
drivers/gpu/drm/i915/intel_pm.c +8 -0
+	/* 2a: Program RC6 thresholds.*/
+	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
+	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+
+	for_each_ring(ring, dev_priv, i)
+		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+

I915_WRITE(GEN6_RC_SLEEP, 0);
missing?

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev)

Quoted 13 lines
drivers/gpu/drm/i915/intel_pm.c +12 -0
+	I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+
+	/* allows RC6 residency counter to work */
+	I915_WRITE(VLV_COUNTER_CONTROL,
+		   _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+				      VLV_MEDIA_RC6_COUNT_EN |
+				      VLV_RENDER_RC6_COUNT_EN));
+
+	/* Todo: If BIOS has not configured PCBR
+	 *       then allocate in BIOS Reserved */
+
+	/* For now we assume BIOS is allocating and populating the PCBR
 */

Both comments do not match with the code.

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev) · line 3907

Quoted 8 lines
drivers/gpu/drm/i915/intel_pm.c +8 -0
+	pcbr = I915_READ(VLV_PCBR);
+
+	DRM_DEBUG_DRIVER("PCBR offset : 0x%x\n", pcbr);
+
+	/* 3: Enable RC6 */
+	if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
+						(pcbr >> VLV_PCBR_ADDR_SHIFT))
+		rc6_mode = GEN6_RC_CTL_EI_MODE(1) | VLV_RC_CTL_CTX_RST_PARALLEL;
                                                    ^^

Bit 24 is not used with chv.

-Mika

Quoted 72 lines
drivers/gpu/drm/i915/intel_pm.c +6 -0
+
+	I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
+
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+}
+
 static void valleyview_enable_rps(struct drm_device *dev)
 {
drivers/gpu/drm/i915/intel_pm.c +14 -6
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4624,13 +4719,17 @@ void intel_init_gt_powersave(struct drm_device *dev)
 {
 	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		cherryview_init_gt_powersave(dev);
+	else if (IS_VALLEYVIEW(dev))
 		valleyview_init_gt_powersave(dev);
 }
 
 void intel_cleanup_gt_powersave(struct drm_device *dev)
 {
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		return;
+	else if (IS_VALLEYVIEW(dev))
 		valleyview_cleanup_gt_powersave(dev);
 }
 
@@ -4644,11 +4743,13 @@ void intel_disable_gt_powersave(struct drm_device *dev)
 	if (IS_IRONLAKE_M(dev)) {
 		ironlake_disable_drps(dev);
 		ironlake_disable_rc6(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
 		cancel_work_sync(&dev_priv->rps.work);
 		mutex_lock(&dev_priv->rps.hw_lock);
-		if (IS_VALLEYVIEW(dev))
+		if (IS_CHERRYVIEW(dev))
+			cherryview_disable_rps(dev);
+		else if (IS_VALLEYVIEW(dev))
 			valleyview_disable_rps(dev);
 		else
 			gen6_disable_rps(dev);
@@ -4666,7 +4767,9 @@ static void intel_gen6_powersave_work(struct work_struct *work)
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev)) {
+		cherryview_enable_rps(dev);
+	} else if (IS_VALLEYVIEW(dev)) {
 		valleyview_enable_rps(dev);
 	} else if (IS_BROADWELL(dev)) {
 		gen8_enable_rps(dev);
@@ -4691,7 +4794,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
 		mutex_unlock(&dev->struct_mutex);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		/*
 		 * PCU communication is slow and this doesn't need to be
 		 * done at any specific time, so do this out of our fast path
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
author
#9 lore raw

Re: [PATCH 03/10] drm/i915/chv: Enable Render Standby (RC6) for Cherryview

Quoted 72 lines · Mika Kuoppala

Hi Deepak,

Quoted 68 lines · [email protected] writes:

From: Deepak S <[email protected]>

v2: Configure PCBR if BIOS fails allocate pcbr (deepak)

v3: Fix PCBR condition check during CHV RC6 Enable flag set

v4: Fixup PCBR comment msg. (Chris)
Rebase against latest code (Deak)
Fixup Spurious hunk (Ben)

---
  drivers/gpu/drm/i915/i915_reg.h |   2 +
  drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++---
  2 files changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +2 -0
index c850254..b4074fd 100644
@@ -962,6 +962,8 @@ enum punit_power_well {
  #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
  #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
  #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
  #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
  #define EIR		0x020b0
  #define EMR		0x020b4
drivers/gpu/drm/i915/intel_pm.c +23 -0
index ebb5c88..f0359b6 100644
@@ -3300,6 +3300,13 @@ static void gen6_disable_rps(struct drm_device *dev)
  		gen6_disable_rps_interrupts(dev);
  }
 
+static void cherryview_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RC_CONTROL, 0);
+}
+
  static void valleyview_disable_rps(struct drm_device *dev)
  {
  	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3722,6 +3729,33 @@ static void valleyview_check_pctx(struct drm_i915_private *dev_priv)
  			     dev_priv->vlv_pctx->stolen->start);
  }
 
+
+/* Check that the pcbr address is not empty. */
+static void cherryview_check_pctx(struct drm_i915_private *dev_priv)
+{
+	unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
+
+	WARN_ON((pctx_addr >> VLV_PCBR_ADDR_SHIFT) == 0);
+}
+
+static void cherryview_setup_pctx(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long pctx_paddr;
+	struct i915_gtt *gtt = &dev_priv->gtt;
+	u32 pcbr;
+	int pctx_size = 32*1024;
Quoted 8 lines

drivers/gpu/drm/i915/intel_pm.c static void valleyview_check_pctx(struct drm_i915_private *dev_priv) · line 3752

Quoted 5 lines
drivers/gpu/drm/i915/intel_pm.c +5 -0
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	pcbr = I915_READ(VLV_PCBR);
+	if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {

I admit that address zero locked by bios is prolly in realms of paranoia. But I would still omit shift here to get lock bit taken into consideration.

Agreed, But verifying address is more important right? We are more concerned with address than lock bit right?

Quoted 6 lines

drivers/gpu/drm/i915/intel_pm.c static void valleyview_check_pctx(struct drm_i915_private *dev_priv) · line 3755

Quoted 3 lines
drivers/gpu/drm/i915/intel_pm.c +3 -0
+		pctx_paddr = (dev_priv->mm.stolen_base +
+			      (gtt->stolen_size - pctx_size));
+		I915_WRITE(VLV_PCBR, pctx_paddr);

In here tho I would mask the low bits out, just to be on the safe side. If we get off by one on stolen calculation we end up writing the lock bit.

I will add the mask bit

Quoted 7 lines

I am thinking that we should just sanity check that bios
has set this up and that it seems to be in correct place. If not, spit a warning and leave rc6 disabled.

The BIOS should have setup everything for us. Why do we need this PCBR setup?

Nice Point, We need to make sure BIOS is setting up the PCBR properly.

Quoted 44 lines
Quoted 32 lines
drivers/gpu/drm/i915/intel_pm.c +20 -0
+	}
+}
+
  static void valleyview_setup_pctx(struct drm_device *dev)
  {
  	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3811,11 +3845,72 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
  	mutex_unlock(&dev_priv->rps.hw_lock);
  }
 
+static void cherryview_init_gt_powersave(struct drm_device *dev)
+{
+	cherryview_setup_pctx(dev);
+}
+
  static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
  {
  	valleyview_cleanup_pctx(dev);
  }
 
+static void cherryview_enable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	u32 gtfifodbg, rc6_mode = 0, pcbr;
+	int i;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	gtfifodbg = I915_READ(GTFIFODBG);
+	if (gtfifodbg) {
+		DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev) · line 3879

Quoted 10 lines
drivers/gpu/drm/i915/intel_pm.c +10 -0
+				 gtfifodbg);
+		I915_WRITE(GTFIFODBG, gtfifodbg);
+	}
+
+	cherryview_check_pctx(dev_priv);
+
+	/* 1a & 1b: Get forcewake during program sequence. Although the driver
+	 * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+

I915_WRITE(GEN6_RC_CONTROL, 0);

Quoted 10 lines

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev) · line 3887

Quoted 8 lines
drivers/gpu/drm/i915/intel_pm.c +8 -0
+	/* 2a: Program RC6 thresholds.*/
+	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
+	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+
+	for_each_ring(ring, dev_priv, i)
+		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+

I915_WRITE(GEN6_RC_SLEEP, 0);
missing?

This might not be need. let me check back. As the default is already 0. I will check the spec and add if needed.

Quoted 6 lines
Quoted 6 lines
drivers/gpu/drm/i915/intel_pm.c +6 -0
+	I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+
+	/* allows RC6 residency counter to work */
+	I915_WRITE(VLV_COUNTER_CONTROL,
+		   _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+				      VLV_MEDIA_RC6_COUNT_EN |
Quoted 8 lines

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev)

Quoted 7 lines
drivers/gpu/drm/i915/intel_pm.c +6 -0
+				      VLV_RENDER_RC6_COUNT_EN));
+
+	/* Todo: If BIOS has not configured PCBR
+	 *       then allocate in BIOS Reserved */
+
+	/* For now we assume BIOS is allocating and populating the PCBR
 */

Both comments do not match with the code.

I will address the comments

Quoted 9 lines

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev) · line 3907

Quoted 8 lines
drivers/gpu/drm/i915/intel_pm.c +8 -0
+	pcbr = I915_READ(VLV_PCBR);
+
+	DRM_DEBUG_DRIVER("PCBR offset : 0x%x\n", pcbr);
+
+	/* 3: Enable RC6 */
+	if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
+						(pcbr >> VLV_PCBR_ADDR_SHIFT))
+		rc6_mode = GEN6_RC_CTL_EI_MODE(1) | VLV_RC_CTL_CTX_RST_PARALLEL;
                                                     ^^
Quoted 3 lines

Bit 24 is not used with chv.

-Mika

I will remove this :) Missed while addressing previous comments

Quoted 68 lines
Quoted 68 lines
drivers/gpu/drm/i915/intel_pm.c +6 -0
+
+	I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
+
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+}
+
  static void valleyview_enable_rps(struct drm_device *dev)
  {
  	struct drm_i915_private *dev_priv = dev->dev_private;
drivers/gpu/drm/i915/intel_pm.c +14 -6
@@ -4624,13 +4719,17 @@ void intel_init_gt_powersave(struct drm_device *dev)
  {
  	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		cherryview_init_gt_powersave(dev);
+	else if (IS_VALLEYVIEW(dev))
  		valleyview_init_gt_powersave(dev);
  }
 
  void intel_cleanup_gt_powersave(struct drm_device *dev)
  {
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		return;
+	else if (IS_VALLEYVIEW(dev))
  		valleyview_cleanup_gt_powersave(dev);
  }
 
@@ -4644,11 +4743,13 @@ void intel_disable_gt_powersave(struct drm_device *dev)
  	if (IS_IRONLAKE_M(dev)) {
  		ironlake_disable_drps(dev);
  		ironlake_disable_rc6(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
  		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
  		cancel_work_sync(&dev_priv->rps.work);
  		mutex_lock(&dev_priv->rps.hw_lock);
-		if (IS_VALLEYVIEW(dev))
+		if (IS_CHERRYVIEW(dev))
+			cherryview_disable_rps(dev);
+		else if (IS_VALLEYVIEW(dev))
  			valleyview_disable_rps(dev);
  		else
  			gen6_disable_rps(dev);
@@ -4666,7 +4767,9 @@ static void intel_gen6_powersave_work(struct work_struct *work)
 
  	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev)) {
+		cherryview_enable_rps(dev);
+	} else if (IS_VALLEYVIEW(dev)) {
  		valleyview_enable_rps(dev);
  	} else if (IS_BROADWELL(dev)) {
  		gen8_enable_rps(dev);
@@ -4691,7 +4794,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
  		ironlake_enable_rc6(dev);
  		intel_init_emon(dev);
  		mutex_unlock(&dev->struct_mutex);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
  		/*
  		 * PCU communication is slow and this doesn't need to be
  		 * done at any specific time, so do this out of our fast path
Signature · 1 line
1.9.1
Quoted 4 lines
Quoted 4 lines

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Thanks for the review.

#10 lore raw

PATCH v5 1/1 drm/i915/chv: Enable Render Standby (RC6) for Cherryview

In reply to [email protected]

From: Deepak S <[email protected]>

v2: Configure PCBR if BIOS fails allocate pcbr (deepak)

v3: Fix PCBR condition check during CHV RC6 Enable flag set

v4: Fixup PCBR comment msg. (Chris)
Rebase against latest code (Deak)
Fixup Spurious hunk (Ben)

v5: Fix PCBR and commentis msg (mika)

---
 drivers/gpu/drm/i915/i915_reg.h |   2 +
 drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +2 -0
index c850254..b4074fd 100644
@@ -962,6 +962,8 @@ enum punit_power_well {
 #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
 #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
 #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
 #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
 #define EIR		0x020b0
 #define EMR		0x020b4
drivers/gpu/drm/i915/intel_pm.c +109 -6

170 lines not on this page · raw message

Signature · 1 line
1.9.1
author
#11 lore raw

Re: [PATCH v5] drm/i915/chv: Enable Render Standby (RC6) for Cherryview

Hi Mika,

On the PCBR check comment. I will create a separate patch to address both VLV and CHV

Thanks
Deepak

Quoted 213 lines · On Thursday 15 May 2014 03:27 PM, [email protected] wrote:

From: Deepak S <[email protected]>

v2: Configure PCBR if BIOS fails allocate pcbr (deepak)

v3: Fix PCBR condition check during CHV RC6 Enable flag set

v4: Fixup PCBR comment msg. (Chris)
Rebase against latest code (Deak)
Fixup Spurious hunk (Ben)

v5: Fix PCBR and commentis msg (mika)

---
  drivers/gpu/drm/i915/i915_reg.h |   2 +
  drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++---
  2 files changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +2 -0
index c850254..b4074fd 100644
@@ -962,6 +962,8 @@ enum punit_power_well {
  #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
  #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
  #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
  #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
  #define EIR		0x020b0
  #define EMR		0x020b4
drivers/gpu/drm/i915/intel_pm.c +109 -6
index 270b659..7a6e50e 100644
@@ -3301,6 +3301,13 @@ static void gen6_disable_rps(struct drm_device *dev)
  		gen6_disable_rps_interrupts(dev);
  }
 
+static void cherryview_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RC_CONTROL, 0);
+}
+
  static void valleyview_disable_rps(struct drm_device *dev)
  {
  	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3723,6 +3730,35 @@ static void valleyview_check_pctx(struct drm_i915_private *dev_priv)
  			     dev_priv->vlv_pctx->stolen->start);
  }
 
+
+/* Check that the pcbr address is not empty. */
+static void cherryview_check_pctx(struct drm_i915_private *dev_priv)
+{
+	unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
+
+	WARN_ON((pctx_addr >> VLV_PCBR_ADDR_SHIFT) == 0);
+}
+
+static void cherryview_setup_pctx(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long pctx_paddr, paddr;
+	struct i915_gtt *gtt = &dev_priv->gtt;
+	u32 pcbr;
+	int pctx_size = 32*1024;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	pcbr = I915_READ(VLV_PCBR);
+	if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
+		paddr = (dev_priv->mm.stolen_base +
+			 (gtt->stolen_size - pctx_size));
+
+		pctx_paddr = (paddr & (~4095));
+		I915_WRITE(VLV_PCBR, pctx_paddr);
+	}
+}
+
  static void valleyview_setup_pctx(struct drm_device *dev)
  {
  	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3812,11 +3848,70 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
  	mutex_unlock(&dev_priv->rps.hw_lock);
  }
 
+static void cherryview_init_gt_powersave(struct drm_device *dev)
+{
+	cherryview_setup_pctx(dev);
+}
+
  static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
  {
  	valleyview_cleanup_pctx(dev);
  }
 
+static void cherryview_enable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	u32 gtfifodbg, rc6_mode = 0, pcbr;
+	int i;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	gtfifodbg = I915_READ(GTFIFODBG);
+	if (gtfifodbg) {
+		DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",
+				 gtfifodbg);
+		I915_WRITE(GTFIFODBG, gtfifodbg);
+	}
+
+	cherryview_check_pctx(dev_priv);
+
+	/* 1a & 1b: Get forcewake during program sequence. Although the driver
+	 * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+
+	/* 2a: Program RC6 thresholds.*/
+	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
+	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+
+	for_each_ring(ring, dev_priv, i)
+		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	I915_WRITE(GEN6_RC_SLEEP, 0);
+
+	I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+
+	/* allows RC6 residency counter to work */
+	I915_WRITE(VLV_COUNTER_CONTROL,
+		   _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+				      VLV_MEDIA_RC6_COUNT_EN |
+				      VLV_RENDER_RC6_COUNT_EN));
+
+	/* For now we assume BIOS is allocating and populating the PCBR  */
+	pcbr = I915_READ(VLV_PCBR);
+
+	DRM_DEBUG_DRIVER("PCBR offset : 0x%x\n", pcbr);
+
+	/* 3: Enable RC6 */
+	if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
+						(pcbr >> VLV_PCBR_ADDR_SHIFT))
+		rc6_mode = GEN6_RC_CTL_EI_MODE(1);
+
+	I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
+
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+}
+
  static void valleyview_enable_rps(struct drm_device *dev)
  {
  	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4625,13 +4720,17 @@ void intel_init_gt_powersave(struct drm_device *dev)
  {
  	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		cherryview_init_gt_powersave(dev);
+	else if (IS_VALLEYVIEW(dev))
  		valleyview_init_gt_powersave(dev);
  }
 
  void intel_cleanup_gt_powersave(struct drm_device *dev)
  {
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		return;
+	else if (IS_VALLEYVIEW(dev))
  		valleyview_cleanup_gt_powersave(dev);
  }
 
@@ -4645,11 +4744,13 @@ void intel_disable_gt_powersave(struct drm_device *dev)
  	if (IS_IRONLAKE_M(dev)) {
  		ironlake_disable_drps(dev);
  		ironlake_disable_rc6(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
  		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
  		cancel_work_sync(&dev_priv->rps.work);
  		mutex_lock(&dev_priv->rps.hw_lock);
-		if (IS_VALLEYVIEW(dev))
+		if (IS_CHERRYVIEW(dev))
+			cherryview_disable_rps(dev);
+		else if (IS_VALLEYVIEW(dev))
  			valleyview_disable_rps(dev);
  		else
  			gen6_disable_rps(dev);
@@ -4667,7 +4768,9 @@ static void intel_gen6_powersave_work(struct work_struct *work)
 
  	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev)) {
+		cherryview_enable_rps(dev);
+	} else if (IS_VALLEYVIEW(dev)) {
  		valleyview_enable_rps(dev);
  	} else if (IS_BROADWELL(dev)) {
  		gen8_enable_rps(dev);
@@ -4692,7 +4795,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
  		ironlake_enable_rc6(dev);
  		intel_init_emon(dev);
  		mutex_unlock(&dev->struct_mutex);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
  		/*
  		 * PCU communication is slow and this doesn't need to be
  		 * done at any specific time, so do this out of our fast path
#12 lore raw

Re: [PATCH v5] drm/i915/chv: Enable Render Standby (RC6) for Cherryview

In reply to [email protected]
Quoted 111 lines · [email protected] writes:

From: Deepak S <[email protected]>

v2: Configure PCBR if BIOS fails allocate pcbr (deepak)

v3: Fix PCBR condition check during CHV RC6 Enable flag set

v4: Fixup PCBR comment msg. (Chris)
Rebase against latest code (Deak)
Fixup Spurious hunk (Ben)

v5: Fix PCBR and commentis msg (mika)

---
 drivers/gpu/drm/i915/i915_reg.h |   2 +
 drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +2 -0
index c850254..b4074fd 100644
@@ -962,6 +962,8 @@ enum punit_power_well {
 #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
 #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
 #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
 #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
 #define EIR		0x020b0
 #define EMR		0x020b4
drivers/gpu/drm/i915/intel_pm.c +52 -0
index 270b659..7a6e50e 100644
@@ -3301,6 +3301,13 @@ static void gen6_disable_rps(struct drm_device *dev)
 		gen6_disable_rps_interrupts(dev);
 }
 
+static void cherryview_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RC_CONTROL, 0);
+}
+
 static void valleyview_disable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3723,6 +3730,35 @@ static void valleyview_check_pctx(struct drm_i915_private *dev_priv)
 			     dev_priv->vlv_pctx->stolen->start);
 }
 
+
+/* Check that the pcbr address is not empty. */
+static void cherryview_check_pctx(struct drm_i915_private *dev_priv)
+{
+	unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
+
+	WARN_ON((pctx_addr >> VLV_PCBR_ADDR_SHIFT) == 0);
+}
+
+static void cherryview_setup_pctx(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long pctx_paddr, paddr;
+	struct i915_gtt *gtt = &dev_priv->gtt;
+	u32 pcbr;
+	int pctx_size = 32*1024;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	pcbr = I915_READ(VLV_PCBR);
+	if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
+		paddr = (dev_priv->mm.stolen_base +
+			 (gtt->stolen_size - pctx_size));
+
+		pctx_paddr = (paddr & (~4095));
+		I915_WRITE(VLV_PCBR, pctx_paddr);
+	}
+}
+
 static void valleyview_setup_pctx(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3812,11 +3848,70 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
 	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
+static void cherryview_init_gt_powersave(struct drm_device *dev)
+{
+	cherryview_setup_pctx(dev);
+}
+
 static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
 {
 	valleyview_cleanup_pctx(dev);
 }
 
+static void cherryview_enable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	u32 gtfifodbg, rc6_mode = 0, pcbr;
+	int i;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	gtfifodbg = I915_READ(GTFIFODBG);
+	if (gtfifodbg) {

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev) · line 3881

Quoted 10 lines
drivers/gpu/drm/i915/intel_pm.c +10 -0
+		DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",
+				 gtfifodbg);
+		I915_WRITE(GTFIFODBG, gtfifodbg);
+	}
+
+	cherryview_check_pctx(dev_priv);
+
+	/* 1a & 1b: Get forcewake during program sequence. Although the driver
+	 * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);

You are starting to configure rc6 with the possibility that bios has already enabled it.

I am still convinced there should be

+ I915_WRITE(GEN6_RC_CONTROL, 0);

in here.

-Mika

Quoted 98 lines
drivers/gpu/drm/i915/intel_pm.c +46 -6
+	/* 2a: Program RC6 thresholds.*/
+	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
+	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+
+	for_each_ring(ring, dev_priv, i)
+		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	I915_WRITE(GEN6_RC_SLEEP, 0);
+
+	I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+
+	/* allows RC6 residency counter to work */
+	I915_WRITE(VLV_COUNTER_CONTROL,
+		   _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+				      VLV_MEDIA_RC6_COUNT_EN |
+				      VLV_RENDER_RC6_COUNT_EN));
+
+	/* For now we assume BIOS is allocating and populating the PCBR  */
+	pcbr = I915_READ(VLV_PCBR);
+
+	DRM_DEBUG_DRIVER("PCBR offset : 0x%x\n", pcbr);
+
+	/* 3: Enable RC6 */
+	if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
+						(pcbr >> VLV_PCBR_ADDR_SHIFT))
+		rc6_mode = GEN6_RC_CTL_EI_MODE(1);
+
+	I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
+
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+}
+
 static void valleyview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4625,13 +4720,17 @@ void intel_init_gt_powersave(struct drm_device *dev)
 {
 	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		cherryview_init_gt_powersave(dev);
+	else if (IS_VALLEYVIEW(dev))
 		valleyview_init_gt_powersave(dev);
 }
 
 void intel_cleanup_gt_powersave(struct drm_device *dev)
 {
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		return;
+	else if (IS_VALLEYVIEW(dev))
 		valleyview_cleanup_gt_powersave(dev);
 }
 
@@ -4645,11 +4744,13 @@ void intel_disable_gt_powersave(struct drm_device *dev)
 	if (IS_IRONLAKE_M(dev)) {
 		ironlake_disable_drps(dev);
 		ironlake_disable_rc6(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
 		cancel_work_sync(&dev_priv->rps.work);
 		mutex_lock(&dev_priv->rps.hw_lock);
-		if (IS_VALLEYVIEW(dev))
+		if (IS_CHERRYVIEW(dev))
+			cherryview_disable_rps(dev);
+		else if (IS_VALLEYVIEW(dev))
 			valleyview_disable_rps(dev);
 		else
 			gen6_disable_rps(dev);
@@ -4667,7 +4768,9 @@ static void intel_gen6_powersave_work(struct work_struct *work)
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev)) {
+		cherryview_enable_rps(dev);
+	} else if (IS_VALLEYVIEW(dev)) {
 		valleyview_enable_rps(dev);
 	} else if (IS_BROADWELL(dev)) {
 		gen8_enable_rps(dev);
@@ -4692,7 +4795,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
 		mutex_unlock(&dev->struct_mutex);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		/*
 		 * PCU communication is slow and this doesn't need to be
 		 * done at any specific time, so do this out of our fast path
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by
#13 lore raw

Re: [PATCH v5] drm/i915/chv: Enable Render Standby (RC6) for Cherryview

Quoted 127 lines · Mika Kuoppala
Quoted 111 lines · [email protected] writes:

From: Deepak S <[email protected]>

v2: Configure PCBR if BIOS fails allocate pcbr (deepak)

v3: Fix PCBR condition check during CHV RC6 Enable flag set

v4: Fixup PCBR comment msg. (Chris)
Rebase against latest code (Deak)
Fixup Spurious hunk (Ben)

v5: Fix PCBR and commentis msg (mika)

---
 drivers/gpu/drm/i915/i915_reg.h |   2 +
 drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +2 -0
index c850254..b4074fd 100644
@@ -962,6 +962,8 @@ enum punit_power_well {
 #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
 #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
 #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
 #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
 #define EIR		0x020b0
 #define EMR		0x020b4
drivers/gpu/drm/i915/intel_pm.c +52 -0
index 270b659..7a6e50e 100644
@@ -3301,6 +3301,13 @@ static void gen6_disable_rps(struct drm_device *dev)
 		gen6_disable_rps_interrupts(dev);
 }
 
+static void cherryview_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RC_CONTROL, 0);
+}
+
 static void valleyview_disable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3723,6 +3730,35 @@ static void valleyview_check_pctx(struct drm_i915_private *dev_priv)
 			     dev_priv->vlv_pctx->stolen->start);
 }
 
+
+/* Check that the pcbr address is not empty. */
+static void cherryview_check_pctx(struct drm_i915_private *dev_priv)
+{
+	unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
+
+	WARN_ON((pctx_addr >> VLV_PCBR_ADDR_SHIFT) == 0);
+}
+
+static void cherryview_setup_pctx(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long pctx_paddr, paddr;
+	struct i915_gtt *gtt = &dev_priv->gtt;
+	u32 pcbr;
+	int pctx_size = 32*1024;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	pcbr = I915_READ(VLV_PCBR);
+	if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
+		paddr = (dev_priv->mm.stolen_base +
+			 (gtt->stolen_size - pctx_size));
+
+		pctx_paddr = (paddr & (~4095));
+		I915_WRITE(VLV_PCBR, pctx_paddr);
+	}
+}
+
 static void valleyview_setup_pctx(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3812,11 +3848,70 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
 	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
+static void cherryview_init_gt_powersave(struct drm_device *dev)
+{
+	cherryview_setup_pctx(dev);
+}
+
 static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
 {
 	valleyview_cleanup_pctx(dev);
 }
 
+static void cherryview_enable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	u32 gtfifodbg, rc6_mode = 0, pcbr;
+	int i;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	gtfifodbg = I915_READ(GTFIFODBG);
+	if (gtfifodbg) {

drivers/gpu/drm/i915/intel_pm.c static void valleyview_init_gt_powersave(struct drm_device *dev) · line 3881

Quoted 10 lines
drivers/gpu/drm/i915/intel_pm.c +10 -0
+		DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",
+				 gtfifodbg);
+		I915_WRITE(GTFIFODBG, gtfifodbg);
+	}
+
+	cherryview_check_pctx(dev_priv);
+
+	/* 1a & 1b: Get forcewake during program sequence. Although the driver
+	 * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);

You are starting to configure rc6 with the possibility that bios has already enabled it.

Quoted 5 lines

I am still convinced there should be

+ I915_WRITE(GEN6_RC_CONTROL, 0);

in here.

I forgot to mention that with that addition made,
you can add

Quoted 100 lines

-Mika

Quoted 98 lines
drivers/gpu/drm/i915/intel_pm.c +46 -6
+	/* 2a: Program RC6 thresholds.*/
+	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
+	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+
+	for_each_ring(ring, dev_priv, i)
+		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	I915_WRITE(GEN6_RC_SLEEP, 0);
+
+	I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+
+	/* allows RC6 residency counter to work */
+	I915_WRITE(VLV_COUNTER_CONTROL,
+		   _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+				      VLV_MEDIA_RC6_COUNT_EN |
+				      VLV_RENDER_RC6_COUNT_EN));
+
+	/* For now we assume BIOS is allocating and populating the PCBR  */
+	pcbr = I915_READ(VLV_PCBR);
+
+	DRM_DEBUG_DRIVER("PCBR offset : 0x%x\n", pcbr);
+
+	/* 3: Enable RC6 */
+	if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
+						(pcbr >> VLV_PCBR_ADDR_SHIFT))
+		rc6_mode = GEN6_RC_CTL_EI_MODE(1);
+
+	I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
+
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+}
+
 static void valleyview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4625,13 +4720,17 @@ void intel_init_gt_powersave(struct drm_device *dev)
 {
 	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		cherryview_init_gt_powersave(dev);
+	else if (IS_VALLEYVIEW(dev))
 		valleyview_init_gt_powersave(dev);
 }
 
 void intel_cleanup_gt_powersave(struct drm_device *dev)
 {
-	if (IS_VALLEYVIEW(dev))
+	if (IS_CHERRYVIEW(dev))
+		return;
+	else if (IS_VALLEYVIEW(dev))
 		valleyview_cleanup_gt_powersave(dev);
 }
 
@@ -4645,11 +4744,13 @@ void intel_disable_gt_powersave(struct drm_device *dev)
 	if (IS_IRONLAKE_M(dev)) {
 		ironlake_disable_drps(dev);
 		ironlake_disable_rc6(dev);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
 		cancel_work_sync(&dev_priv->rps.work);
 		mutex_lock(&dev_priv->rps.hw_lock);
-		if (IS_VALLEYVIEW(dev))
+		if (IS_CHERRYVIEW(dev))
+			cherryview_disable_rps(dev);
+		else if (IS_VALLEYVIEW(dev))
 			valleyview_disable_rps(dev);
 		else
 			gen6_disable_rps(dev);
@@ -4667,7 +4768,9 @@ static void intel_gen6_powersave_work(struct work_struct *work)
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev)) {
+		cherryview_enable_rps(dev);
+	} else if (IS_VALLEYVIEW(dev)) {
 		valleyview_enable_rps(dev);
 	} else if (IS_BROADWELL(dev)) {
 		gen8_enable_rps(dev);
@@ -4692,7 +4795,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
 		mutex_unlock(&dev->struct_mutex);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		/*
 		 * PCU communication is slow and this doesn't need to be
 		 * done at any specific time, so do this out of our fast path
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#14 lore raw

PATCH v5 1/8 drm/i915/chv: Enable Render Standby (RC6) for Cherryview

In reply to Mika Kuoppala

From: Deepak S <[email protected]>

v2: Configure PCBR if BIOS fails allocate pcbr (deepak)

v3: Fix PCBR condition check during CHV RC6 Enable flag set

v4: Fixup PCBR comment msg. (Chris)
Rebase against latest code (Deak)
Fixup Spurious hunk (Ben)

v5: Fix PCBR and commentis msg (mika)

---
 drivers/gpu/drm/i915/i915_reg.h |   2 +
 drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +2 -0
index c850254..b4074fd 100644
@@ -962,6 +962,8 @@ enum punit_power_well {
 #define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
 #define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
 #define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT	12
+
 #define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
 #define EIR		0x020b0
 #define EMR		0x020b4
drivers/gpu/drm/i915/intel_pm.c +109 -6

170 lines not on this page · raw message

Signature · 1 line
1.9.1
#15 lore raw

PATCH 4/10 drm/i915/chv: Added CHV specific register read and write

In reply to [email protected]

From: Deepak S <[email protected]>

Support to individually control Media/Render well based on the register access. Add CHV specific write function to habdle difference between registers that are sadowed vs those that need forcewake even for writes.

v2: Drop write FIFO for CHV and add comman well forcewake (Ville)

v3: Fix for decrementing fw count in chv read/write. (Deepak)

[vsyrjala: Move the register range macros into intel_uncore.c]
---
 drivers/gpu/drm/i915/intel_uncore.c | 133 +++++++++++++++++++++++++++++++++---
 1 file changed, 125 insertions(+), 8 deletions(-)
drivers/gpu/drm/i915/intel_uncore.c +125 -8
index 76dc185..4f1f199 100644
@@ -495,6 +495,31 @@ void assert_force_wake_inactive(struct drm_i915_private *dev_priv)
 	((reg) >= 0x22000 && (reg) < 0x24000) ||\
 	((reg) >= 0x30000 && (reg) < 0x40000))
 
+#define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
+	(((reg) >= 0x2000 && (reg) < 0x4000) ||\
+	((reg) >= 0x5000 && (reg) < 0x8000) ||\
+	((reg) >= 0x8300 && (reg) < 0x8500) ||\
+	((reg) >= 0xB000 && (reg) < 0xC000) ||\
+	((reg) >= 0xE000 && (reg) < 0xE800))
+
+#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)\
+	(((reg) >= 0x8800 && (reg) < 0x8900) ||\
+	((reg) >= 0xD000 && (reg) < 0xD800) ||\
+	((reg) >= 0x12000 && (reg) < 0x14000) ||\
+	((reg) >= 0x1A000 && (reg) < 0x1C000) ||\
+	((reg) >= 0x1E800 && (reg) < 0x1EA00) ||\
+	((reg) >= 0x30000 && (reg) < 0x40000))
+
+#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)\
+	(((reg) >= 0x4000 && (reg) < 0x5000) ||\
+	((reg) >= 0x8000 && (reg) < 0x8300) ||\
+	((reg) >= 0x8500 && (reg) < 0x8600) ||\
+	((reg) >= 0x9000 && (reg) < 0xB000) ||\
+	((reg) >= 0xC000 && (reg) < 0xc800) ||\
+	((reg) >= 0xF000 && (reg) < 0x10000) ||\
+	((reg) >= 0x14000 && (reg) < 0x14400) ||\
+	((reg) >= 0x22000 && (reg) < 0x24000))
+
 static void
 ilk_dummy_write(struct drm_i915_private *dev_priv)
 {
@@ -588,7 +613,45 @@ vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
 	REG_READ_FOOTER; \
 }
 
+#define __chv_read(x) \
+static u##x \
+chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+	unsigned fwengine = 0; \
+	REG_READ_HEADER(x); \
+	if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_MEDIA; \
+	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_ALL; \
+	if (FORCEWAKE_RENDER & fwengine) { \
+		if (dev_priv->uncore.fw_rendercount++ == 0) \
+			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+								fwengine); \
+	} \
+	if (FORCEWAKE_MEDIA & fwengine) { \
+		if (dev_priv->uncore.fw_mediacount++ == 0) \
+			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+								fwengine); \
+	} \
+	val = __raw_i915_read##x(dev_priv, reg); \
+	if (FORCEWAKE_RENDER & fwengine) { \
+		if (--dev_priv->uncore.fw_rendercount == 0) \
+			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+								fwengine); \
+	} \
+	if (FORCEWAKE_MEDIA & fwengine) { \
+		if (--dev_priv->uncore.fw_mediacount == 0) \
+			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+								fwengine); \
+	} \
+	REG_READ_FOOTER; \
+}
 
+__chv_read(8)
+__chv_read(16)
+__chv_read(32)
+__chv_read(64)
 __vlv_read(8)
 __vlv_read(16)
 __vlv_read(32)
@@ -606,6 +669,7 @@ __gen4_read(16)
 __gen4_read(32)
 __gen4_read(64)
 
+#undef __chv_read
 #undef __vlv_read
 #undef __gen6_read
 #undef __gen5_read
@@ -710,6 +774,46 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
 	REG_WRITE_FOOTER; \
 }
 
+#define __chv_write(x) \
+static void \
+chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+	unsigned fwengine = 0; \
+	bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \
+	REG_WRITE_HEADER; \
+	if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_MEDIA; \
+	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_ALL; \
+	if (__needs_put && (FORCEWAKE_RENDER & fwengine)) { \
+			if (dev_priv->uncore.fw_rendercount++ == 0) \
+				(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+									fwengine); \
+	} \
+	if (__needs_put && (FORCEWAKE_MEDIA & fwengine)) { \
+		if (dev_priv->uncore.fw_mediacount++ == 0) \
+			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+								fwengine); \
+	} \
+	__raw_i915_write##x(dev_priv, reg, val); \
+	if (__needs_put && (FORCEWAKE_RENDER & fwengine)) { \
+			if (--dev_priv->uncore.fw_rendercount == 0) \
+				(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+									fwengine); \
+	} \
+	if (__needs_put && (FORCEWAKE_MEDIA & fwengine)) { \
+		if (--dev_priv->uncore.fw_mediacount == 0) \
+			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+								fwengine); \
+	} \
+	REG_WRITE_FOOTER; \
+}
+
+__chv_write(8)
+__chv_write(16)
+__chv_write(32)
+__chv_write(64)
 __gen8_write(8)
 __gen8_write(16)
 __gen8_write(32)
@@ -731,6 +835,7 @@ __gen4_write(16)
 __gen4_write(32)
 __gen4_write(64)
 
+#undef __chv_write
 #undef __gen8_write
 #undef __hsw_write
 #undef __gen6_write
@@ -794,14 +899,26 @@ void intel_uncore_init(struct drm_device *dev)
 
 	switch (INTEL_INFO(dev)->gen) {
 	default:
-		dev_priv->uncore.funcs.mmio_writeb  = gen8_write8;
-		dev_priv->uncore.funcs.mmio_writew  = gen8_write16;
-		dev_priv->uncore.funcs.mmio_writel  = gen8_write32;
-		dev_priv->uncore.funcs.mmio_writeq  = gen8_write64;
-		dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
-		dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
-		dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
-		dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+		if (IS_CHERRYVIEW(dev)) {
+			dev_priv->uncore.funcs.mmio_writeb  = chv_write8;
+			dev_priv->uncore.funcs.mmio_writew  = chv_write16;
+			dev_priv->uncore.funcs.mmio_writel  = chv_write32;
+			dev_priv->uncore.funcs.mmio_writeq  = chv_write64;
+			dev_priv->uncore.funcs.mmio_readb  = chv_read8;
+			dev_priv->uncore.funcs.mmio_readw  = chv_read16;
+			dev_priv->uncore.funcs.mmio_readl  = chv_read32;
+			dev_priv->uncore.funcs.mmio_readq  = chv_read64;
+
+		} else {
+			dev_priv->uncore.funcs.mmio_writeb  = gen8_write8;
+			dev_priv->uncore.funcs.mmio_writew  = gen8_write16;
+			dev_priv->uncore.funcs.mmio_writel  = gen8_write32;
+			dev_priv->uncore.funcs.mmio_writeq  = gen8_write64;
+			dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
+			dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
+			dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
+			dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+		}
 		break;
 	case 7:
 	case 6:
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#16 lore raw

Re: [PATCH 04/10] drm/i915/chv: Added CHV specific register read and write

Quoted 41 lines · [email protected] writes:

From: Deepak S <[email protected]>

Support to individually control Media/Render well based on the register access. Add CHV specific write function to habdle difference between registers that are sadowed vs those that need forcewake even for writes.

v2: Drop write FIFO for CHV and add comman well forcewake (Ville)

v3: Fix for decrementing fw count in chv read/write. (Deepak)

[vsyrjala: Move the register range macros into intel_uncore.c]
---
 drivers/gpu/drm/i915/intel_uncore.c | 133 +++++++++++++++++++++++++++++++++---
 1 file changed, 125 insertions(+), 8 deletions(-)
drivers/gpu/drm/i915/intel_uncore.c +16 -0
index 76dc185..4f1f199 100644
@@ -495,6 +495,31 @@ void assert_force_wake_inactive(struct drm_i915_private *dev_priv)
 	((reg) >= 0x22000 && (reg) < 0x24000) ||\
 	((reg) >= 0x30000 && (reg) < 0x40000))
 
+#define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
+	(((reg) >= 0x2000 && (reg) < 0x4000) ||\
+	((reg) >= 0x5000 && (reg) < 0x8000) ||\
+	((reg) >= 0x8300 && (reg) < 0x8500) ||\
+	((reg) >= 0xB000 && (reg) < 0xC000) ||\
+	((reg) >= 0xE000 && (reg) < 0xE800))
+
+#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)\
+	(((reg) >= 0x8800 && (reg) < 0x8900) ||\
+	((reg) >= 0xD000 && (reg) < 0xD800) ||\
+	((reg) >= 0x12000 && (reg) < 0x14000) ||\
+	((reg) >= 0x1A000 && (reg) < 0x1C000) ||\
+	((reg) >= 0x1E800 && (reg) < 0x1EA00) ||\
+	((reg) >= 0x30000 && (reg) < 0x40000))
+
+#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)\

drivers/gpu/drm/i915/intel_uncore.c void assert_force_wake_inactive(struct drm_i915_private *dev_priv) · line 523

Quoted 10 lines
drivers/gpu/drm/i915/intel_uncore.c +9 -0
+	(((reg) >= 0x4000 && (reg) < 0x5000) ||\
+	((reg) >= 0x8000 && (reg) < 0x8300) ||\
+	((reg) >= 0x8500 && (reg) < 0x8600) ||\
+	((reg) >= 0x9000 && (reg) < 0xB000) ||\
+	((reg) >= 0xC000 && (reg) < 0xc800) ||\
+	((reg) >= 0xF000 && (reg) < 0x10000) ||\
 
+	((reg) >= 0x14000 && (reg) < 0x14400) ||\
+	((reg) >= 0x22000 && (reg) < 0x24000))
+

For these two last register ranges I couldnt find an indication if we really need to take fw. I guess it doesnt hurt but please re-check if these are truely needed.

Quoted 18 lines
drivers/gpu/drm/i915/intel_uncore.c +0 -0
 static void
 ilk_dummy_write(struct drm_i915_private *dev_priv)

{

drivers/gpu/drm/i915/intel_uncore.c +11 -0
@@ -588,7 +613,45 @@ vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
 	REG_READ_FOOTER; \
 }
 
+#define __chv_read(x) \
+static u##x \
+chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+	unsigned fwengine = 0; \
+	REG_READ_HEADER(x); \
+	if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_MEDIA; \
+	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_ALL; \

drivers/gpu/drm/i915/intel_uncore.c vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ · line 636

Quoted 10 lines
drivers/gpu/drm/i915/intel_uncore.c +10 -0
+	if (FORCEWAKE_RENDER & fwengine) { \
+		if (dev_priv->uncore.fw_rendercount++ == 0) \
+			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+								fwengine); \
+	} \
+	if (FORCEWAKE_MEDIA & fwengine) { \
+		if (dev_priv->uncore.fw_mediacount++ == 0) \
+			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+								fwengine); \
+	} \

This patch introduces a bug in here because we end up waking up the same well twice in a row, by delivering fwengine into the wake func.

The following patch in the series fixes this bug. You should squash these two into a single patch.

-Mika

Quoted 126 lines
drivers/gpu/drm/i915/intel_uncore.c +79 -8
+	val = __raw_i915_read##x(dev_priv, reg); \
+	if (FORCEWAKE_RENDER & fwengine) { \
+		if (--dev_priv->uncore.fw_rendercount == 0) \
+			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+								fwengine); \
+	} \
+	if (FORCEWAKE_MEDIA & fwengine) { \
+		if (--dev_priv->uncore.fw_mediacount == 0) \
+			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+								fwengine); \
+	} \
+	REG_READ_FOOTER; \
+}
 
+__chv_read(8)
+__chv_read(16)
+__chv_read(32)
+__chv_read(64)
 __vlv_read(8)
 __vlv_read(16)
 __vlv_read(32)
@@ -606,6 +669,7 @@ __gen4_read(16)
 __gen4_read(32)
 __gen4_read(64)
 
+#undef __chv_read
 #undef __vlv_read
 #undef __gen6_read
 #undef __gen5_read
@@ -710,6 +774,46 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
 	REG_WRITE_FOOTER; \
 }
 
+#define __chv_write(x) \
+static void \
+chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+	unsigned fwengine = 0; \
+	bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \
+	REG_WRITE_HEADER; \
+	if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_MEDIA; \
+	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \
+		fwengine = FORCEWAKE_ALL; \
+	if (__needs_put && (FORCEWAKE_RENDER & fwengine)) { \
+			if (dev_priv->uncore.fw_rendercount++ == 0) \
+				(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+									fwengine); \
+	} \
+	if (__needs_put && (FORCEWAKE_MEDIA & fwengine)) { \
+		if (dev_priv->uncore.fw_mediacount++ == 0) \
+			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+								fwengine); \
+	} \
+	__raw_i915_write##x(dev_priv, reg, val); \
+	if (__needs_put && (FORCEWAKE_RENDER & fwengine)) { \
+			if (--dev_priv->uncore.fw_rendercount == 0) \
+				(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+									fwengine); \
+	} \
+	if (__needs_put && (FORCEWAKE_MEDIA & fwengine)) { \
+		if (--dev_priv->uncore.fw_mediacount == 0) \
+			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+								fwengine); \
+	} \
+	REG_WRITE_FOOTER; \
+}
+
+__chv_write(8)
+__chv_write(16)
+__chv_write(32)
+__chv_write(64)
 __gen8_write(8)
 __gen8_write(16)
 __gen8_write(32)
@@ -731,6 +835,7 @@ __gen4_write(16)
 __gen4_write(32)
 __gen4_write(64)
 
+#undef __chv_write
 #undef __gen8_write
 #undef __hsw_write
 #undef __gen6_write
@@ -794,14 +899,26 @@ void intel_uncore_init(struct drm_device *dev)
 
 	switch (INTEL_INFO(dev)->gen) {
 	default:
-		dev_priv->uncore.funcs.mmio_writeb  = gen8_write8;
-		dev_priv->uncore.funcs.mmio_writew  = gen8_write16;
-		dev_priv->uncore.funcs.mmio_writel  = gen8_write32;
-		dev_priv->uncore.funcs.mmio_writeq  = gen8_write64;
-		dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
-		dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
-		dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
-		dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+		if (IS_CHERRYVIEW(dev)) {
+			dev_priv->uncore.funcs.mmio_writeb  = chv_write8;
+			dev_priv->uncore.funcs.mmio_writew  = chv_write16;
+			dev_priv->uncore.funcs.mmio_writel  = chv_write32;
+			dev_priv->uncore.funcs.mmio_writeq  = chv_write64;
+			dev_priv->uncore.funcs.mmio_readb  = chv_read8;
+			dev_priv->uncore.funcs.mmio_readw  = chv_read16;
+			dev_priv->uncore.funcs.mmio_readl  = chv_read32;
+			dev_priv->uncore.funcs.mmio_readq  = chv_read64;
+
+		} else {
+			dev_priv->uncore.funcs.mmio_writeb  = gen8_write8;
+			dev_priv->uncore.funcs.mmio_writew  = gen8_write16;
+			dev_priv->uncore.funcs.mmio_writel  = gen8_write32;
+			dev_priv->uncore.funcs.mmio_writeq  = gen8_write64;
+			dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
+			dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
+			dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
+			dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+		}
 		break;
 	case 7:
 	case 6:
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

#17 lore raw

PATCH 5/10 drm/i915/chv: Streamline CHV forcewake stuff

In reply to [email protected]

From: Deepak S <[email protected]>

Streamline the CHV forcewake functions just like was done for VLV.

This will also fix a bug in accessing the common well registers, where we'd end up trying to wake up the wells too many times since we'd call force_wake_get/put twice per register access, with FORCEFAKE_ALL both times.

v2: Re-factor CHV/VLV Forcewake offsets (Ben)

---
 drivers/gpu/drm/i915/intel_uncore.c | 148 ++++++++++++++++--------------------
 1 file changed, 66 insertions(+), 82 deletions(-)
drivers/gpu/drm/i915/intel_uncore.c +66 -82
index 4f1f199..d1a8c72 100644
@@ -484,41 +484,43 @@ void assert_force_wake_inactive(struct drm_i915_private *dev_priv)
 #define NEEDS_FORCE_WAKE(dev_priv, reg) \
 	 ((reg) < 0x40000 && (reg) != FORCEWAKE)
 
+#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
+
 #define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
-	(((reg) >= 0x2000 && (reg) < 0x4000) ||\
-	((reg) >= 0x5000 && (reg) < 0x8000) ||\
-	((reg) >= 0xB000 && (reg) < 0x12000) ||\
-	((reg) >= 0x2E000 && (reg) < 0x30000))
+	(REG_RANGE((reg), 0x2000, 0x4000) || \
+	 REG_RANGE((reg), 0x5000, 0x8000) || \
+	 REG_RANGE((reg), 0xB000, 0x12000) || \
+	 REG_RANGE((reg), 0x2E000, 0x30000))
 
-#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\
-	(((reg) >= 0x12000 && (reg) < 0x14000) ||\
-	((reg) >= 0x22000 && (reg) < 0x24000) ||\
-	((reg) >= 0x30000 && (reg) < 0x40000))
+#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg) \
+	(REG_RANGE((reg), 0x12000, 0x14000) || \
+	 REG_RANGE((reg), 0x22000, 0x24000) || \
+	 REG_RANGE((reg), 0x30000, 0x40000))
 
 #define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
-	(((reg) >= 0x2000 && (reg) < 0x4000) ||\
-	((reg) >= 0x5000 && (reg) < 0x8000) ||\
-	((reg) >= 0x8300 && (reg) < 0x8500) ||\
-	((reg) >= 0xB000 && (reg) < 0xC000) ||\
-	((reg) >= 0xE000 && (reg) < 0xE800))
-
-#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)\
-	(((reg) >= 0x8800 && (reg) < 0x8900) ||\
-	((reg) >= 0xD000 && (reg) < 0xD800) ||\
-	((reg) >= 0x12000 && (reg) < 0x14000) ||\
-	((reg) >= 0x1A000 && (reg) < 0x1C000) ||\
-	((reg) >= 0x1E800 && (reg) < 0x1EA00) ||\
-	((reg) >= 0x30000 && (reg) < 0x40000))
-
-#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)\
-	(((reg) >= 0x4000 && (reg) < 0x5000) ||\
-	((reg) >= 0x8000 && (reg) < 0x8300) ||\
-	((reg) >= 0x8500 && (reg) < 0x8600) ||\
-	((reg) >= 0x9000 && (reg) < 0xB000) ||\
-	((reg) >= 0xC000 && (reg) < 0xc800) ||\
-	((reg) >= 0xF000 && (reg) < 0x10000) ||\
-	((reg) >= 0x14000 && (reg) < 0x14400) ||\
-	((reg) >= 0x22000 && (reg) < 0x24000))
+	(REG_RANGE((reg), 0x2000, 0x4000) || \
+	 REG_RANGE((reg), 0x5000, 0x8000) || \
+	 REG_RANGE((reg), 0x8300, 0x8500) || \
+	 REG_RANGE((reg), 0xB000, 0xC000) || \
+	 REG_RANGE((reg), 0xE000, 0xE800))
+
+#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg) \
+	(REG_RANGE((reg), 0x8800, 0x8900) || \
+	 REG_RANGE((reg), 0xD000, 0xD800) || \
+	 REG_RANGE((reg), 0x12000, 0x14000) || \
+	 REG_RANGE((reg), 0x1A000, 0x1C000) || \
+	 REG_RANGE((reg), 0x1E800, 0x1EA00) || \
+	 REG_RANGE((reg), 0x30000, 0x40000))
+
+#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg) \
+	(REG_RANGE((reg), 0x4000, 0x5000) || \
+	 REG_RANGE((reg), 0x8000, 0x8300) || \
+	 REG_RANGE((reg), 0x8500, 0x8600) || \
+	 REG_RANGE((reg), 0x9000, 0xB000) || \
+	 REG_RANGE((reg), 0xC000, 0xC800) || \
+	 REG_RANGE((reg), 0xF000, 0x10000) || \
+	 REG_RANGE((reg), 0x14000, 0x14400) || \
+	 REG_RANGE((reg), 0x22000, 0x24000))
 
 static void
 ilk_dummy_write(struct drm_i915_private *dev_priv)
@@ -618,33 +620,23 @@ static u##x \
 chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
 	unsigned fwengine = 0; \
 	REG_READ_HEADER(x); \
-	if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \
-		fwengine = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \
-		fwengine = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \
-		fwengine = FORCEWAKE_ALL; \
-	if (FORCEWAKE_RENDER & fwengine) { \
-		if (dev_priv->uncore.fw_rendercount++ == 0) \
-			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
-								fwengine); \
-	} \
-	if (FORCEWAKE_MEDIA & fwengine) { \
-		if (dev_priv->uncore.fw_mediacount++ == 0) \
-			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
-								fwengine); \
+	if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \
+		if (dev_priv->uncore.fw_rendercount == 0) \
+			fwengine = FORCEWAKE_RENDER; \
+	} else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \
+		if (dev_priv->uncore.fw_mediacount == 0) \
+			fwengine = FORCEWAKE_MEDIA; \
+	} else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \
+		if (dev_priv->uncore.fw_rendercount == 0) \
+			fwengine |= FORCEWAKE_RENDER; \
+		if (dev_priv->uncore.fw_mediacount == 0) \
+			fwengine |= FORCEWAKE_MEDIA; \
 	} \
+	if (fwengine) \
+		dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
 	val = __raw_i915_read##x(dev_priv, reg); \
-	if (FORCEWAKE_RENDER & fwengine) { \
-		if (--dev_priv->uncore.fw_rendercount == 0) \
-			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
-								fwengine); \
-	} \
-	if (FORCEWAKE_MEDIA & fwengine) { \
-		if (--dev_priv->uncore.fw_mediacount == 0) \
-			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
-								fwengine); \
-	} \
+	if (fwengine) \
+		dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
 	REG_READ_FOOTER; \
 }
 
@@ -778,35 +770,27 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
 static void \
 chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
 	unsigned fwengine = 0; \
-	bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \
+	bool shadowed = is_gen8_shadowed(dev_priv, reg); \
 	REG_WRITE_HEADER; \
-	if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \
-		fwengine = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \
-		fwengine = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \
-		fwengine = FORCEWAKE_ALL; \
-	if (__needs_put && (FORCEWAKE_RENDER & fwengine)) { \
-			if (dev_priv->uncore.fw_rendercount++ == 0) \
-				(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
-									fwengine); \
-	} \
-	if (__needs_put && (FORCEWAKE_MEDIA & fwengine)) { \
-		if (dev_priv->uncore.fw_mediacount++ == 0) \
-			(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
-								fwengine); \
+	if (!shadowed) { \
+		if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \
+			if (dev_priv->uncore.fw_rendercount == 0) \
+				fwengine = FORCEWAKE_RENDER; \
+		} else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \
+			if (dev_priv->uncore.fw_mediacount == 0) \
+				fwengine = FORCEWAKE_MEDIA; \
+		} else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \
+			if (dev_priv->uncore.fw_rendercount == 0) \
+				fwengine |= FORCEWAKE_RENDER; \
+			if (dev_priv->uncore.fw_mediacount == 0) \
+				fwengine |= FORCEWAKE_MEDIA; \
+		} \
 	} \
+	if (fwengine) \
+		dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
 	__raw_i915_write##x(dev_priv, reg, val); \
-	if (__needs_put && (FORCEWAKE_RENDER & fwengine)) { \
-			if (--dev_priv->uncore.fw_rendercount == 0) \
-				(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
-									fwengine); \
-	} \
-	if (__needs_put && (FORCEWAKE_MEDIA & fwengine)) { \
-		if (--dev_priv->uncore.fw_mediacount == 0) \
-			(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
-								fwengine); \
-	} \
+	if (fwengine) \
+		dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
 	REG_WRITE_FOOTER; \
 }
 
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#18 lore raw

PATCH 6/10 drm/i915/chv: Enable RPS (Turbo) for Cherryview

In reply to [email protected]

From: Deepak S <[email protected]>

v2: Disable media turbo and Add DOWN_IDLE_AVG support (Ville)

v3: Mass rename of the dev_priv->rps variables in upstream.

v4: Rebase against latest code. (Deepak)

---
 drivers/gpu/drm/i915/i915_drv.h       |  1 +
 drivers/gpu/drm/i915/i915_reg.h       | 10 ++++
 drivers/gpu/drm/i915/intel_pm.c       | 95 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_sideband.c | 15 ++++++
 4 files changed, 120 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_drv.h +1 -0
index 5f4f631..e70a9f0 100644
@@ -2552,6 +2552,7 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
 u32 vlv_punit_read(struct drm_i915_private *dev_priv, u8 addr);
 void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val);
 u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr);
+u32 chv_nc_read(struct drm_i915_private *dev_priv, u8 addr);
 u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg);
 void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg);
drivers/gpu/drm/i915/i915_reg.h +10 -0
index b4074fd..3ff34c4 100644
@@ -475,6 +475,7 @@
 #define VLV_IOSF_DATA				(VLV_DISPLAY_BASE + 0x2104)
 #define VLV_IOSF_ADDR				(VLV_DISPLAY_BASE + 0x2108)
 
+#define   CHV_IOSF_PORT_NC			0x04
 /* See configdb bunit SB addr map */
 #define BUNIT_REG_BISOC				0x11
 
@@ -520,6 +521,14 @@ enum punit_power_well {
 #define PUNIT_FUSE_BUS2				0xf6 /* bits 47:40 */
 #define PUNIT_FUSE_BUS1				0xf5 /* bits 55:48 */
 
+#define CHV_IOSF_NC_FB_GFX_FREQ_FUSE		0xdb
+#define CHV_FB_GFX_MAX_FREQ_FUSE_SHIFT		16
+#define CHV_FB_GFX_MAX_FREQ_FUSE_MASK		0xff
+
+#define CHV_IOSF_NC_FB_GFX_RPE_FUSE		0xdf
+#define CHV_FB_RPE_FREQ_SHIFT			8
+#define CHV_FB_RPE_FREQ_MASK			0xff
+
 #define IOSF_NC_FB_GFX_FREQ_FUSE		0x1c
 #define   FB_GFX_MAX_FREQ_FUSE_SHIFT		3
 #define   FB_GFX_MAX_FREQ_FUSE_MASK		0x000007f8
@@ -747,6 +756,7 @@ enum punit_power_well {
 #define   SANDYBRIDGE_FENCE_PITCH_SHIFT	32
 #define   GEN7_FENCE_MAX_PITCH_VAL	0x0800
 
+
 /* control register for cpu gtt access */
 #define TILECTL				0x101000
 #define   TILECTL_SWZCTL			(1 << 0)
drivers/gpu/drm/i915/intel_pm.c +94 -1

120 lines not on this page · raw message

drivers/gpu/drm/i915/intel_sideband.c +15 -0
index b1a5514..8f6904d 100644
@@ -106,6 +106,21 @@ void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
 			PUNIT_OPCODE_REG_WRITE, reg, &val);
 }
 
+u32 chv_nc_read(struct drm_i915_private *dev_priv, u8 addr)
+{
+	u32 val = 0;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	mutex_lock(&dev_priv->dpio_lock);
+	vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), CHV_IOSF_PORT_NC,
+			PUNIT_OPCODE_REG_READ, addr, &val);
+	mutex_unlock(&dev_priv->dpio_lock);
+
+	return val;
+}
+
+
 u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr)
 {
 	u32 val = 0;
Signature · 1 line
1.9.1
#19 lore raw

PATCH 7/10 drm/i915/chv: CHV doesn't need WaRsForcewakeWaitTC0

In reply to [email protected]

From: Ville Syrjälä <[email protected]>

Skip __gen6_gt_wait_for_thread_c0() on CHV.

---
 drivers/gpu/drm/i915/intel_uncore.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_uncore.c +2 -2
index d1a8c72..b719c51 100644
@@ -229,8 +229,8 @@ static void __vlv_force_wake_get(struct drm_i915_private *dev_priv,
 	}
 
 	/* WaRsForcewakeWaitTC0:vlv */
-	__gen6_gt_wait_for_thread_c0(dev_priv);
-
+	if (!IS_CHERRYVIEW(dev_priv->dev))
+		__gen6_gt_wait_for_thread_c0(dev_priv);
 }
 
 static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#20 lore raw

PATCH 8/10 drm/i915/chv: Skip gen6_gt_check_fifodbg() on CHV

In reply to [email protected]

From: Ville Syrjälä <[email protected]>

CHV uses the gen8 shadow register mechanism so we shouldn't be checking the GT FIFO status.

This effectively removes the posting read, so add an explicit posting read using FORCEWAKE_ACK_VLV (which is what use in vlv_forcewake_reset()).

---
 drivers/gpu/drm/i915/intel_uncore.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/intel_uncore.c +4 -3
index b719c51..fa6e01e 100644
@@ -248,9 +248,10 @@ static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
 		__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
 				_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
 
-	/* The below doubles as a POSTING_READ */
-	gen6_gt_check_fifodbg(dev_priv);
-
+	/* something from same cacheline, but !FORCEWAKE_VLV */
+	__raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
+	if (!IS_CHERRYVIEW(dev_priv->dev))
+		gen6_gt_check_fifodbg(dev_priv);
 }
 
 static void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#21 lore raw

PATCH 9/10 drm/i915/chv: Added CHV specific DDR fetch into init_clock_gating

In reply to [email protected]

From: Deepak S <[email protected]>

[vsyrjala: Fix merge fubmle where the code ended up in g4x_disable_trickle_feed() instead of cherryview_init_clock_gating()]

---
 drivers/gpu/drm/i915/intel_pm.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
drivers/gpu/drm/i915/intel_pm.c +11 -0
index dedbdf3..0d9b831 100644
@@ -3985,7 +3985,18 @@ static void cherryview_enable_rps(struct drm_device *dev)
 		   GEN6_RP_UP_BUSY_AVG |
 		   GEN6_RP_DOWN_IDLE_AVG);
 
+	/* ToDo: Update the mem freq based on latest spec [CHV]*/
 	val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+	switch ((val >> 6) & 3) {
+	case 0:
+	case 1:
+	case 2:
+		dev_priv->mem_freq = 1600;
+		break;
+	case 3:
+		dev_priv->mem_freq = 2000;
+		break;
+	}
 
 	DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
 	DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#22 lore raw

PATCH 10/10 drm/i915/chv: Freq(opcode) request for CHV.

In reply to [email protected]

From: Deepak S <[email protected]>

On CHV, All the freq request should be even. So, we need to make sure we request the opcode accordingly.

---
 drivers/gpu/drm/i915/i915_drv.h | 1 +
 drivers/gpu/drm/i915/i915_irq.c | 9 +++++++--
 drivers/gpu/drm/i915/i915_reg.h | 3 +++
 3 files changed, 11 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +1 -0
index e70a9f0..3966ff2 100644
@@ -1318,6 +1318,7 @@ struct drm_i915_private {
 	u32 gt_irq_mask;
 	u32 pm_irq_mask;
 	u32 pm_rps_events;
+	u32 pm_rps_freq_req;
 	u32 pipestat_irq_mask[I915_MAX_PIPES];
 
 	struct work_struct hotplug_work;
drivers/gpu/drm/i915/i915_irq.c +7 -2
index 6af51ad..3e8bcca 100644
@@ -1162,7 +1162,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 		if (adj > 0)
 			adj *= 2;
 		else
-			adj = 1;
+			adj = dev_priv->pm_rps_freq_req;
 		new_delay = dev_priv->rps.cur_freq + adj;
 
 		/*
@@ -1181,7 +1181,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 		if (adj < 0)
 			adj *= 2;
 		else
-			adj = -1;
+			adj = -1 * dev_priv->pm_rps_freq_req;
 		new_delay = dev_priv->rps.cur_freq + adj;
 	} else { /* unknown event */
 		new_delay = dev_priv->rps.cur_freq;
@@ -4088,6 +4088,11 @@ void intel_irq_init(struct drm_device *dev)
 	/* Let's track the enabled rps events */
 	dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
 
+	if (IS_CHERRYVIEW(dev))
+		dev_priv->pm_rps_freq_req = CHV_GPU_FREQ_REQ;
+	else
+		dev_priv->pm_rps_freq_req = GEN6_GPU_FREQ_REQ;
+
 	setup_timer(&dev_priv->gpu_error.hangcheck_timer,
 		    i915_hangcheck_elapsed,
 		    (unsigned long) dev);
drivers/gpu/drm/i915/i915_reg.h +3 -0
index 3ff34c4..4998d6b 100644
@@ -529,6 +529,9 @@ enum punit_power_well {
 #define CHV_FB_RPE_FREQ_SHIFT			8
 #define CHV_FB_RPE_FREQ_MASK			0xff
 
+#define CHV_GPU_FREQ_REQ			2
+#define GEN6_GPU_FREQ_REQ			1
+
 #define IOSF_NC_FB_GFX_FREQ_FUSE		0x1c
 #define   FB_GFX_MAX_FREQ_FUSE_SHIFT		3
 #define   FB_GFX_MAX_FREQ_FUSE_MASK		0x000007f8
Signature · 1 line
1.9.1
#23 lore raw

Re: [PATCH 10/10] drm/i915/chv: Freq(opcode) request for CHV.

Quoted 39 lines · On Mon, May 05, 2014 at 06:17:39PM +0530, [email protected] wrote:

From: Deepak S <[email protected]>

On CHV, All the freq request should be even. So, we need to make sure we request the opcode accordingly.

---
 drivers/gpu/drm/i915/i915_drv.h | 1 +
 drivers/gpu/drm/i915/i915_irq.c | 9 +++++++--
 drivers/gpu/drm/i915/i915_reg.h | 3 +++
 3 files changed, 11 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +1 -0
index e70a9f0..3966ff2 100644
@@ -1318,6 +1318,7 @@ struct drm_i915_private {
 	u32 gt_irq_mask;
 	u32 pm_irq_mask;
 	u32 pm_rps_events;
+	u32 pm_rps_freq_req;
 	u32 pipestat_irq_mask[I915_MAX_PIPES];
 
 	struct work_struct hotplug_work;
drivers/gpu/drm/i915/i915_irq.c +1 -1
index 6af51ad..3e8bcca 100644
@@ -1162,7 +1162,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 		if (adj > 0)
 			adj *= 2;
 		else
-			adj = 1;
+			adj = dev_priv->pm_rps_freq_req;
 		new_delay = dev_priv->rps.cur_freq + adj;
 
 		/*

drivers/gpu/drm/i915/i915_irq.c static void gen6_pm_rps_work(struct work_struct *work) · line 1184

Quoted 5 lines
drivers/gpu/drm/i915/i915_irq.c +1 -1
@@ -1181,7 +1181,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 		if (adj < 0)
 			adj *= 2;
 		else
-			adj = -1;
+			adj = -1 * dev_priv->pm_rps_freq_req;

I'm not sure pm_rps_freq_req is very descriptive. Maybe it's better to just open code the thing and add a few comments. Eg.:
/* CHV requires even values */
adj = IS_CHERRYVIEW(dev) ? 2 : 1;
...
/* CHV requires even values */
adj = IS_CHERRYVIEW(dev) ? -2 : -1;

drivers/gpu/drm/i915/i915_irq.c static void gen6_pm_rps_work(struct work_struct *work) · line 1185

Quoted 1 line
drivers/gpu/drm/i915/i915_irq.c +0 -0
 		new_delay = dev_priv->rps.cur_freq + adj;

In any case this doesn't seem to enough to guarantee an even value. You'd also need to make sure efficient_freq, min_freq_softlimit and max_freq_softlimit are even.

The alternative is to just make the final value even in valleyview_set_rps(), but then you might still trip these
WARN_ON(val > dev_priv->rps.max_freq_softlimit); WARN_ON(val < dev_priv->rps.min_freq_softlimit);
in there. So I guess it's back to option 1 and making sure all the limits are also even. Also leaving it up to valleyview_set_rps() could introduce a slight delay before the frequency starts to change since it could effectively ignore the first interrupt (depending on which way it's going and which we we would round the final value).

Quoted 19 lines
drivers/gpu/drm/i915/i915_irq.c +5 -0
 	} else { /* unknown event */
 		new_delay = dev_priv->rps.cur_freq;
@@ -4088,6 +4088,11 @@ void intel_irq_init(struct drm_device *dev)
 	/* Let's track the enabled rps events */
 	dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
 
+	if (IS_CHERRYVIEW(dev))
+		dev_priv->pm_rps_freq_req = CHV_GPU_FREQ_REQ;
+	else
+		dev_priv->pm_rps_freq_req = GEN6_GPU_FREQ_REQ;
+
 	setup_timer(&dev_priv->gpu_error.hangcheck_timer,
 		    i915_hangcheck_elapsed,
 		    (unsigned long) dev);
drivers/gpu/drm/i915/i915_reg.h +0 -0
index 3ff34c4..4998d6b 100644

drivers/gpu/drm/i915/i915_reg.h enum punit_power_well { · line 533

Quoted 5 lines
drivers/gpu/drm/i915/i915_reg.h +2 -0
@@ -529,6 +529,9 @@ enum punit_power_well {
 #define CHV_FB_RPE_FREQ_SHIFT			8
 #define CHV_FB_RPE_FREQ_MASK			0xff
 
+#define CHV_GPU_FREQ_REQ			2
+#define GEN6_GPU_FREQ_REQ			1

I don't think these defines buy us anything. Instead I think just adding a comment or two to where the even vs. odd magic happens should be a better option.

Quoted 11 lines
drivers/gpu/drm/i915/i915_reg.h +1 -0
+
 #define IOSF_NC_FB_GFX_FREQ_FUSE		0x1c
 #define   FB_GFX_MAX_FREQ_FUSE_SHIFT		3
 #define   FB_GFX_MAX_FREQ_FUSE_MASK		0x000007f8
Signature · 6 lines
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 2 lines
Ville Syrjälä
Intel OTC
#24 lore raw

PATCH v2 1/1 drm/i915/chv: Freq(opcode) request for CHV.

In reply to [email protected]

From: Deepak S <[email protected]>

On CHV, All the freq request should be even. So, we need to make sure we request the opcode accordingly.

v2: Avoid vairable for freq request (ville)

---
 drivers/gpu/drm/i915/i915_irq.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +8 -4
index 6af51ad..56e93e8 100644
@@ -1161,8 +1161,10 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
 		if (adj > 0)
 			adj *= 2;
-		else
-			adj = 1;
+		else {
+			/* CHV needs even encode values */
+			adj = IS_CHERRYVIEW(dev_priv->dev) ? 2 : 1;
+		}
 		new_delay = dev_priv->rps.cur_freq + adj;
 
 		/*
@@ -1180,8 +1182,10 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
 		if (adj < 0)
 			adj *= 2;
-		else
-			adj = -1;
+		else {
+			/* CHV needs even encode values */
+			adj = IS_CHERRYVIEW(dev_priv->dev) ? -2 : -1;
+		}
 		new_delay = dev_priv->rps.cur_freq + adj;
 	} else { /* unknown event */
 		new_delay = dev_priv->rps.cur_freq;
Signature · 1 line
1.9.1
#25 lore raw
In reply to [email protected]
Quoted 16 lines · On Mon, May 05, 2014 at 06:17:29PM +0530, [email protected] wrote:

From: Deepak S <[email protected]>

Squashed some of the patches and created a new patch series. Addressed review comments on most of the patches.

Ben Widawsky (1):
drm/i915/bdw: Implement a basic PM interrupt handler

Deepak S (7):
drm/i915: Enable PM Interrupts target via Display Interface. drm/i915/chv: Enable Render Standby (RC6) for Cherryview drm/i915/chv: Added CHV specific register read and write drm/i915/chv: Streamline CHV forcewake stuff drm/i915/chv: Enable RPS (Turbo) for Cherryview drm/i915/chv: Added CHV specific DDR fetch into init_clock_gating drm/i915/chv: Freq(opcode) request for CHV.

Quoted 3 lines

Ville Syrjälä (2):
drm/i915/chv: CHV doesn't need WaRsForcewakeWaitTC0 drm/i915/chv: Skip gen6_gt_check_fifodbg() on CHV

Just for coordination: I've just pulled in the bdw-only series from Mika, so I guess you need to rebase the chv patches on top of drm-intel-nightly. I think -nightly has now enough of the chv stuff merged that this should work out. Otherwise I need to beat up the reviewers to not slack off this much :(
-Daniel

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