Revert "drm/i915: Enable RC6 immediately"
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 21 Jul 2016 20:16:19 +0000 (21:16 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 21 Jul 2016 20:43:19 +0000 (21:43 +0100)
This reverts commit b12e0ee2080c ("drm/i915: Enable RC6 immediately"),
as it was never meant to be sent anywhere other than the bug report for
experimentation.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1469132179-4052-1-git-send-email-chris@chris-wilson.co.uk
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_request.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_uncore.c

index 84e4018b18a730370a7fe64ee774c58791e2d1de..83afdd0597b576c003f3e64db65fe92ef995bc0a 100644 (file)
@@ -1630,6 +1630,7 @@ static int i915_drm_resume(struct drm_device *dev)
 
        intel_opregion_notify_adapter(dev_priv, PCI_D0);
 
+       intel_autoenable_gt_powersave(dev_priv);
        drm_kms_helper_poll_enable(dev);
 
        enable_rpm_wakeref_asserts(dev_priv);
@@ -1811,8 +1812,7 @@ int i915_reset(struct drm_i915_private *dev_priv)
         * previous concerns that it doesn't respond well to some forms
         * of re-init after reset.
         */
-       if (INTEL_GEN(dev_priv) > 5)
-               intel_enable_gt_powersave(dev_priv);
+       intel_autoenable_gt_powersave(dev_priv);
 
        return 0;
 
@@ -2440,7 +2440,6 @@ static int intel_runtime_resume(struct device *device)
        i915_gem_init_swizzling(dev);
 
        intel_runtime_pm_enable_interrupts(dev_priv);
-       intel_enable_gt_powersave(dev_priv);
 
        /*
         * On VLV/CHV display interrupts are part of the display
index 52be86e3e07dabb656e98c6037f380084c336c72..c97724d380d37248ca07ae8f988f017d70413474 100644 (file)
@@ -1192,6 +1192,7 @@ struct intel_gen6_power_mgmt {
        bool client_boost;
 
        bool enabled;
+       struct delayed_work autoenable_work;
        unsigned boosts;
 
        /* manual wa residency calculations */
index 90b9f46d94326ba7f69cca6ce32eaeae2eca24ae..40047eb4882617573c3f125faf3f8796e262ac3f 100644 (file)
@@ -4355,6 +4355,8 @@ i915_gem_suspend(struct drm_device *dev)
        struct drm_i915_private *dev_priv = to_i915(dev);
        int ret = 0;
 
+       intel_suspend_gt_powersave(dev_priv);
+
        mutex_lock(&dev->struct_mutex);
 
        /* We have to flush all the executing contexts to main memory so
index b20b00410510477af7b2a8d640c70b49807e4031..60a3a343b3a89af1e4267f911f89b8dd6fbe94c0 100644 (file)
@@ -405,6 +405,7 @@ static void i915_gem_mark_busy(const struct intel_engine_cs *engine)
        intel_runtime_pm_get_noresume(dev_priv);
        dev_priv->gt.awake = true;
 
+       intel_enable_gt_powersave(dev_priv);
        i915_update_gfx_val(dev_priv);
        if (INTEL_GEN(dev_priv) >= 6)
                gen6_rps_busy(dev_priv);
index 00116092b18a1002bce8baa696a04097c442e463..78beb7e9d3840fe2095edb25ff853ac6950b6fc6 100644 (file)
@@ -15502,7 +15502,6 @@ void intel_modeset_init_hw(struct drm_device *dev)
        dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
 
        intel_init_clock_gating(dev);
-       intel_enable_gt_powersave(dev_priv);
 }
 
 /*
index 8bb98ec32da381797715669c7cb7a8ab7a2ce8b2..e74d851868c5037e5f677008c224882e295d0ac8 100644 (file)
@@ -1691,9 +1691,12 @@ void intel_pm_setup(struct drm_device *dev);
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
 void intel_gpu_ips_teardown(void);
 void intel_init_gt_powersave(struct drm_i915_private *dev_priv);
+void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv);
+void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv);
 void intel_enable_gt_powersave(struct drm_i915_private *dev_priv);
+void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv);
 void intel_disable_gt_powersave(struct drm_i915_private *dev_priv);
-void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv);
+void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv);
 void gen6_rps_busy(struct drm_i915_private *dev_priv);
 void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
 void gen6_rps_idle(struct drm_i915_private *dev_priv);
index 45753e1aa7f14dc98e7e193a97e670cb6e007652..64d628c915a39adadf94c3ecbbb813372fdc3cc7 100644 (file)
@@ -6526,6 +6526,8 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
        dev_priv->rps.boost_freq = dev_priv->rps.max_freq;
 
        mutex_unlock(&dev_priv->rps.hw_lock);
+
+       intel_autoenable_gt_powersave(dev_priv);
 }
 
 void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
@@ -6539,10 +6541,31 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
                intel_runtime_pm_put(dev_priv);
 }
 
+/**
+ * intel_suspend_gt_powersave - suspend PM work and helper threads
+ * @dev_priv: i915 device
+ *
+ * We don't want to disable RC6 or other features here, we just want
+ * to make sure any work we've queued has finished and won't bother
+ * us while we're suspended.
+ */
+void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv)
+{
+       if (INTEL_GEN(dev_priv) < 6)
+               return;
+
+       if (cancel_delayed_work_sync(&dev_priv->rps.autoenable_work))
+               intel_runtime_pm_put(dev_priv);
+
+       /* gen6_rps_idle() will be called later to disable interrupts */
+}
+
 void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv)
 {
        dev_priv->rps.enabled = true; /* force disabling */
        intel_disable_gt_powersave(dev_priv);
+
+       gen6_reset_rps_interrupts(dev_priv);
 }
 
 void intel_disable_gt_powersave(struct drm_i915_private *dev_priv)
@@ -6567,12 +6590,13 @@ void intel_disable_gt_powersave(struct drm_i915_private *dev_priv)
 
        dev_priv->rps.enabled = false;
        mutex_unlock(&dev_priv->rps.hw_lock);
-
-       gen6_reset_rps_interrupts(dev_priv);
 }
 
 void intel_enable_gt_powersave(struct drm_i915_private *dev_priv)
 {
+       /* We shouldn't be disabling as we submit, so this should be less
+        * racy than it appears!
+        */
        if (READ_ONCE(dev_priv->rps.enabled))
                return;
 
@@ -6608,9 +6632,75 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv)
        WARN_ON(dev_priv->rps.efficient_freq < dev_priv->rps.min_freq);
        WARN_ON(dev_priv->rps.efficient_freq > dev_priv->rps.max_freq);
 
+       dev_priv->rps.enabled = true;
        mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
+static void __intel_autoenable_gt_powersave(struct work_struct *work)
+{
+       struct drm_i915_private *dev_priv =
+               container_of(work, typeof(*dev_priv), rps.autoenable_work.work);
+       struct intel_engine_cs *rcs;
+       struct drm_i915_gem_request *req;
+
+       if (READ_ONCE(dev_priv->rps.enabled))
+               goto out;
+
+       rcs = &dev_priv->engine[RCS];
+       if (rcs->last_context)
+               goto out;
+
+       if (!rcs->init_context)
+               goto out;
+
+       mutex_lock(&dev_priv->drm.struct_mutex);
+
+       req = i915_gem_request_alloc(rcs, dev_priv->kernel_context);
+       if (IS_ERR(req))
+               goto unlock;
+
+       if (!i915.enable_execlists && i915_switch_context(req) == 0)
+               rcs->init_context(req);
+
+       /* Mark the device busy, calling intel_enable_gt_powersave() */
+       i915_add_request_no_flush(req);
+
+unlock:
+       mutex_unlock(&dev_priv->drm.struct_mutex);
+out:
+       intel_runtime_pm_put(dev_priv);
+}
+
+void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv)
+{
+       if (READ_ONCE(dev_priv->rps.enabled))
+               return;
+
+       if (IS_IRONLAKE_M(dev_priv)) {
+               ironlake_enable_drps(dev_priv);
+               mutex_lock(&dev_priv->drm.struct_mutex);
+               intel_init_emon(dev_priv);
+               mutex_unlock(&dev_priv->drm.struct_mutex);
+       } else if (INTEL_INFO(dev_priv)->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
+                * to make resume and init faster.
+                *
+                * We depend on the HW RC6 power context save/restore
+                * mechanism when entering D3 through runtime PM suspend. So
+                * disable RPM until RPS/RC6 is properly setup. We can only
+                * get here via the driver load/system resume/runtime resume
+                * paths, so the _noresume version is enough (and in case of
+                * runtime resume it's necessary).
+                */
+               if (queue_delayed_work(dev_priv->wq,
+                                      &dev_priv->rps.autoenable_work,
+                                      round_jiffies_up_relative(HZ)))
+                       intel_runtime_pm_get_noresume(dev_priv);
+       }
+}
+
 static void ibx_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -7716,6 +7806,8 @@ void intel_pm_setup(struct drm_device *dev)
        mutex_init(&dev_priv->rps.hw_lock);
        spin_lock_init(&dev_priv->rps.client_lock);
 
+       INIT_DELAYED_WORK(&dev_priv->rps.autoenable_work,
+                         __intel_autoenable_gt_powersave);
        INIT_LIST_HEAD(&dev_priv->rps.clients);
 
        dev_priv->pm.suspended = false;
index 2d4bca456b004d087ba20bdbdad015fafacadad1..43f833901b8e36780595d96b13a24a68837cd904 100644 (file)
@@ -435,7 +435,7 @@ void intel_uncore_sanitize(struct drm_i915_private *dev_priv)
        i915.enable_rc6 = sanitize_rc6_option(dev_priv, i915.enable_rc6);
 
        /* BIOS often leaves RC6 enabled, but disable it for hw init */
-       intel_disable_gt_powersave(dev_priv);
+       intel_sanitize_gt_powersave(dev_priv);
 }
 
 static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,