drm/i915: put ring frequency and turbo setup into a work queue v5
authorJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 2 Nov 2012 18:14:00 +0000 (11:14 -0700)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sun, 11 Nov 2012 22:51:41 +0000 (23:51 +0100)
Communicating via the mailbox registers with the PCU can take quite
awhile.  And updating the ring frequency or enabling turbo is not
something that needs to happen synchronously, so take it out of our init
and resume paths to speed things up (~200ms on my T420).

v2: add comment about why we use a work queue (Daniel)
    make sure work queue is idle on suspend (Daniel)
    use a delayed work queue since there's no hurry (Daniel)
v3: make cleanup symmetric and just call cancel work directly (Daniel)
v4: schedule the work using round_jiffies_up to batch work better (Chris)
v5: fix the right schedule_delayed_work call (Chris)

References: https://bugs.freedesktop.org/show_bug.cgi?id=54089

Signed-of-by: Jesse Barnes <jbarnes@virtuougseek.org>
[danvet: bikeshed the placement of the new delayed work, move it to
all the other gen6 power mgmt stuff.]
Signed-off-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/intel_pm.c

index cfd8920537c5d32a417335538722c595e0190162..577858bd080938bbb829d4122dbca1028f1ab98b 100644 (file)
@@ -474,6 +474,8 @@ static int i915_drm_freeze(struct drm_device *dev)
                        return error;
                }
 
+               cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
+
                intel_modeset_disable(dev);
 
                drm_irq_uninstall(dev);
index f8fa63deb92ca17864e5770d0e1b044f77d3d4d8..8db7bb9899b93b0650ad4852f843c778cfe4acf6 100644 (file)
@@ -562,6 +562,8 @@ struct intel_gen6_power_mgmt {
        u8 cur_delay;
        u8 min_delay;
        u8 max_delay;
+
+       struct delayed_work delayed_resume_work;
 };
 
 struct intel_ilk_power_mgmt {
index b6d980b0ac4cce8f80167c5bc39c604e997f5f6d..169b416430db2e602142df08bc8e6f14e6f9f984 100644 (file)
@@ -3304,23 +3304,46 @@ static void intel_init_emon(struct drm_device *dev)
 
 void intel_disable_gt_powersave(struct drm_device *dev)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        if (IS_IRONLAKE_M(dev)) {
                ironlake_disable_drps(dev);
                ironlake_disable_rc6(dev);
        } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) {
+               cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
                gen6_disable_rps(dev);
        }
 }
 
+static void intel_gen6_powersave_work(struct work_struct *work)
+{
+       struct drm_i915_private *dev_priv =
+               container_of(work, struct drm_i915_private,
+                            rps.delayed_resume_work.work);
+       struct drm_device *dev = dev_priv->dev;
+
+       mutex_lock(&dev->struct_mutex);
+       gen6_enable_rps(dev);
+       gen6_update_ring_freq(dev);
+       mutex_unlock(&dev->struct_mutex);
+}
+
 void intel_enable_gt_powersave(struct drm_device *dev)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        if (IS_IRONLAKE_M(dev)) {
                ironlake_enable_drps(dev);
                ironlake_enable_rc6(dev);
                intel_init_emon(dev);
        } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
-               gen6_enable_rps(dev);
-               gen6_update_ring_freq(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
+                * to make resume and init faster.
+                */
+               schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
+                                     round_jiffies_up_relative(HZ));
        }
 }
 
@@ -4216,6 +4239,8 @@ void intel_gt_init(struct drm_device *dev)
                dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
                dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
        }
+       INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
+                         intel_gen6_powersave_work);
 }
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val)