drm/i915: vlv: reserve the GT power context only once during driver init
Atm we reserve/allocate and free the power context during GT power
enable/disable time. There is no need to do this, we can reserve/allocate
the buffer once during driver loading and free it during driver cleanup.
The re-reservation can also fail in case the driver previously manages to
allocate something on the given fixed address.
The buffer isn't exepected to move even if allocated by the BIOS, for
safety add an assert to check this assumption.
This also fixed a bug for Ville, where re-reserving the context failed
during a GPU reset (I assume because something else got allocated on its
fixed address).
Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 38a68ce..453bf0c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3201,11 +3201,6 @@
I915_WRITE(GEN6_RC_CONTROL, 0);
gen6_disable_rps_interrupts(dev);
-
- if (dev_priv->vlv_pctx) {
- drm_gem_object_unreference(&dev_priv->vlv_pctx->base);
- dev_priv->vlv_pctx = NULL;
- }
}
static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
@@ -3549,6 +3544,15 @@
return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff;
}
+/* Check that the pctx buffer wasn't move under us. */
+static void valleyview_check_pctx(struct drm_i915_private *dev_priv)
+{
+ unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
+
+ WARN_ON(pctx_addr != dev_priv->mm.stolen_base +
+ dev_priv->vlv_pctx->stolen->start);
+}
+
static void valleyview_setup_pctx(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3593,6 +3597,17 @@
dev_priv->vlv_pctx = pctx;
}
+static void valleyview_cleanup_pctx(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (WARN_ON(!dev_priv->vlv_pctx))
+ return;
+
+ drm_gem_object_unreference(&dev_priv->vlv_pctx->base);
+ dev_priv->vlv_pctx = NULL;
+}
+
static void valleyview_enable_rps(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3602,6 +3617,8 @@
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+ valleyview_check_pctx(dev_priv);
+
if ((gtfifodbg = I915_READ(GTFIFODBG))) {
DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",
gtfifodbg);
@@ -4418,6 +4435,18 @@
dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK);
}
+void intel_init_gt_powersave(struct drm_device *dev)
+{
+ if (IS_VALLEYVIEW(dev))
+ valleyview_setup_pctx(dev);
+}
+
+void intel_cleanup_gt_powersave(struct drm_device *dev)
+{
+ if (IS_VALLEYVIEW(dev))
+ valleyview_cleanup_pctx(dev);
+}
+
void intel_disable_gt_powersave(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4472,8 +4501,6 @@
ironlake_enable_rc6(dev);
intel_init_emon(dev);
} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
- if (IS_VALLEYVIEW(dev))
- valleyview_setup_pctx(dev);
/*
* PCU communication is slow and this doesn't need to be
* done at any specific time, so do this out of our fast path