[PATCH 106/118] drm/i915: Enable rc6 for Ironlake
Chris Wilson
chris at chris-wilson.co.uk
Tue Sep 11 19:50:06 UTC 2018
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_debugfs.c | 16 +++--
drivers/gpu/drm/i915/i915_pci.c | 3 +-
drivers/gpu/drm/i915/intel_gt_pm.c | 104 +++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_gt_pm.h | 2 +
4 files changed, 117 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a21c80659426..03c1d52d78a2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1402,12 +1402,13 @@ static int i915_reset_info(struct seq_file *m, void *unused)
static int ironlake_drpc_info(struct seq_file *m)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- u32 rgvmodectl, rstdbyctl;
+ u32 rgvmodectl, rstdbyctl, pwrctx;
u16 crstandvid;
rgvmodectl = I915_READ(MEMMODECTL);
rstdbyctl = I915_READ(RSTDBYCTL);
crstandvid = I915_READ16(CRSTANDVID);
+ pwrctx = I915_READ(PWRCTXA);
seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN));
seq_printf(m, "Boost freq: %d\n",
@@ -1427,12 +1428,15 @@ static int ironlake_drpc_info(struct seq_file *m)
seq_printf(m, "Min P-state: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
- seq_printf(m, "Render standby enabled: %s\n",
- yesno(!(rstdbyctl & RCX_SW_EXIT)));
+ seq_printf(m, "Render standby: %08x\n", rstdbyctl);
+ seq_printf(m, "RS enabled: %s\n", yesno(!(rstdbyctl & RCX_SW_EXIT)));
+ seq_printf(m, "RS1/RC1 enabled? %s\n", yesno(rstdbyctl & RS1EN));
+ seq_printf(m, "RS2/RC6 enabled? %s\n", yesno(rstdbyctl & RS2EN));
+ seq_printf(m, "RS3/RC6+ enabled? %s\n", yesno(rstdbyctl & RS3EN));
seq_puts(m, "Current RS state: ");
switch (rstdbyctl & RSX_STATUS_MASK) {
case RSX_STATUS_ON:
- seq_puts(m, "on\n");
+ seq_puts(m, "busy\n");
break;
case RSX_STATUS_RC1:
seq_puts(m, "RC1\n");
@@ -1447,12 +1451,14 @@ static int ironlake_drpc_info(struct seq_file *m)
seq_puts(m, "RS2 (RC6)\n");
break;
case RSX_STATUS_RS3:
- seq_puts(m, "RC3 (RC6+)\n");
+ seq_puts(m, "RS3 (RC6+)\n");
break;
default:
seq_puts(m, "unknown\n");
break;
}
+ seq_printf(m, "Power context: %x, enabled? %s\n",
+ pwrctx & ~PWRCTX_EN, yesno(pwrctx & PWRCTX_EN));
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index b06b4df13c87..d9e55e807a73 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -225,8 +225,7 @@ static const struct intel_device_info intel_gm45_info = {
.ring_mask = RENDER_RING | BSD_RING, \
.has_snoop = true, \
.has_coherent_ggtt = true, \
- /* ilk does support rc6, but we do not implement [power] contexts */ \
- .has_rc6 = 0, \
+ .has_rc6 = true, \
GEN_DEFAULT_PIPEOFFSETS, \
GEN_DEFAULT_PAGE_SIZES, \
CURSOR_OFFSETS
diff --git a/drivers/gpu/drm/i915/intel_gt_pm.c b/drivers/gpu/drm/i915/intel_gt_pm.c
index ceb6ee4e1652..eef476915198 100644
--- a/drivers/gpu/drm/i915/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/intel_gt_pm.c
@@ -170,6 +170,30 @@ static void ironlake_disable_drps(struct drm_i915_private *dev_priv)
spin_unlock(&mchdev_lock);
}
+static bool gen5_disable_rs(struct drm_i915_private *dev_priv)
+{
+ I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT);
+ return intel_wait_for_register(dev_priv,
+ RSTDBYCTL,
+ RSX_STATUS_MASK, RSX_STATUS_ON,
+ 50) == 0;
+}
+
+static void gen5_enable_rs(struct drm_i915_private *dev_priv)
+{
+ I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
+}
+
+static void __gen5_enable_rc6(struct drm_i915_private *dev_priv)
+{
+ I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RS2EN);
+}
+
+static void __gen5_disable_rc6(struct drm_i915_private *dev_priv)
+{
+ I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RS2EN);
+}
+
/*
* There's a funny hw issue where the hw returns all 0 when reading from
* GEN6_RP_INTERRUPT_LIMITS. Hence we always need to compute the desired value
@@ -855,8 +879,10 @@ void intel_gt_pm_busy(struct drm_i915_private *dev_priv)
memset(&rps->ei, 0, sizeof(rps->ei));
enable_rps_interrupts(dev_priv);
- if (IS_GEN5(dev_priv))
+ if (IS_GEN5(dev_priv)) {
+ __gen5_disable_rc6(dev_priv);
gen5_update_gfx_val(dev_priv);
+ }
mutex_unlock(&rps->lock);
}
@@ -897,6 +923,9 @@ void intel_gt_pm_idle(struct drm_i915_private *dev_priv)
if (INTEL_GEN(dev_priv) >= 6) {
I915_WRITE(GEN6_PMINTRMSK,
gen6_sanitize_rps_pm_mask(dev_priv, ~0));
+ } else if (INTEL_GEN(dev_priv) >= 5) {
+ gen5_update_gfx_val(dev_priv);
+ __gen5_enable_rc6(dev_priv);
}
rps->last_adj = 0;
@@ -1030,6 +1059,32 @@ static void gen9_disable_rps(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_RP_CONTROL, 0);
}
+static void gen5_enable_rc6(struct drm_i915_private *dev_priv)
+{
+ u32 val;
+
+ gen5_disable_rs(dev_priv);
+
+ I915_WRITE(PWRCTXA, i915_ggtt_offset(dev_priv->gt_pm.pctx) | PWRCTX_EN);
+ POSTING_READ(PWRCTXA);
+
+ val = I915_READ(RSTDBYCTL);
+ val &= ~(RS3EN | D3RS3EN | RCX_SW_EXIT);
+ val |= RS2EN | RS1EN;
+ I915_WRITE(RSTDBYCTL, val);
+}
+
+static void gen5_disable_rc6(struct drm_i915_private *dev_priv)
+{
+ /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */
+ gen5_disable_rs(dev_priv);
+
+ I915_WRITE(PWRCTXA, 0);
+ POSTING_READ(PWRCTXA);
+
+ gen5_enable_rs(dev_priv);
+}
+
static void gen6_disable_rc6(struct drm_i915_private *dev_priv)
{
I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -1899,11 +1954,52 @@ static void ilk_init_frequencies(struct drm_i915_private *i915)
ips->c_m = 2;
}
+static unsigned long ilk_pctx_size(struct drm_i915_private *dev_priv)
+{
+ return (1 + ((I915_READ(PWRCTXA) >> 1) & 0xf)) << 12;
+}
+
static void gen5_init_gt_powersave(struct drm_i915_private *i915)
{
+ struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
+ void __iomem *map;
+ unsigned long sz;
+
ilk_init_frequencies(i915);
ilk_init_emon(i915);
ironlake_init_drps(i915);
+
+ sz = ilk_pctx_size(i915);
+
+ obj = i915_gem_object_create_stolen(i915, sz);
+ if (!obj)
+ obj = i915_gem_object_create_internal(i915, sz);
+ if (IS_ERR(obj))
+ goto err;
+
+ vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+ if (IS_ERR(vma))
+ goto err_obj;
+
+ if (i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_MAPPABLE))
+ goto err_obj;
+
+ map = i915_vma_pin_iomap(vma);
+ if (!IS_ERR(map)) {
+ memset_io(map, 0, sz);
+ i915_vma_unpin_iomap(vma);
+ }
+
+ i915->gt_pm.pctx = vma;
+ return;
+
+err_obj:
+ i915_gem_object_put(obj);
+err:
+ DRM_DEBUG_DRIVER("not enough stolen space for PCTX, disabling\n");
+ mkwrite_device_info(i915)->has_rc6 = 0;
+ intel_runtime_pm_get(i915);
}
static void valleyview_init_gt_powersave(struct drm_i915_private *i915)
@@ -2715,6 +2811,8 @@ static void __enable_rc6(struct drm_i915_private *i915)
gen8_enable_rc6(i915);
else if (INTEL_GEN(i915) >= 6)
gen6_enable_rc6(i915);
+ else if (INTEL_GEN(i915) >= 5)
+ gen5_enable_rc6(i915);
}
void intel_gt_pm_enable_rc6(struct drm_i915_private *i915)
@@ -2800,6 +2898,8 @@ static void __disable_rc6(struct drm_i915_private *i915)
valleyview_disable_rc6(i915);
else if (INTEL_GEN(i915) >= 6)
gen6_disable_rc6(i915);
+ else if (INTEL_GEN(i915) >= 5)
+ gen5_disable_rc6(i915);
}
void intel_gt_pm_disable_rc6(struct drm_i915_private *i915)
@@ -2844,6 +2944,8 @@ void intel_gt_pm_fini(struct drm_i915_private *i915)
if (IS_VALLEYVIEW(i915))
valleyview_cleanup_gt_powersave(i915);
+ i915_vma_unpin_and_release(&i915->gt_pm.pctx, 0);
+
if (!HAS_RC6(i915))
pm_runtime_put(&i915->drm.pdev->dev);
}
diff --git a/drivers/gpu/drm/i915/intel_gt_pm.h b/drivers/gpu/drm/i915/intel_gt_pm.h
index 5f6b1c9cd6c2..25cb9d5e0328 100644
--- a/drivers/gpu/drm/i915/intel_gt_pm.h
+++ b/drivers/gpu/drm/i915/intel_gt_pm.h
@@ -12,6 +12,7 @@
struct drm_i915_private;
struct i915_gem_context;
struct i915_request;
+struct i915_vma;
struct intel_engine_cs;
struct intel_rps_client;
@@ -120,6 +121,7 @@ struct intel_gt_pm {
* global mchdev_lock in intel_gt_pm.c
*/
struct intel_ips ips;
+ struct i915_vma *pctx;
u32 imr;
u32 ier;
--
2.19.0
More information about the Intel-gfx-trybot
mailing list