aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2012-11-02 14:14:00 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-11-11 17:51:41 -0500
commit1a01ab3b2dc4394c46c4c3230805748f632f6f74 (patch)
tree205db1a4fa65822a9a2b63a1fde113e84276396c
parent073f34d9d49bdbadbea8198ddc3fbb7e736a94dd (diff)
drm/i915: put ring frequency and turbo setup into a work queue v5
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>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c29
3 files changed, 31 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index cfd8920537c5..577858bd0809 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -474,6 +474,8 @@ static int i915_drm_freeze(struct drm_device *dev)
474 return error; 474 return error;
475 } 475 }
476 476
477 cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
478
477 intel_modeset_disable(dev); 479 intel_modeset_disable(dev);
478 480
479 drm_irq_uninstall(dev); 481 drm_irq_uninstall(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f8fa63deb92c..8db7bb9899b9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -562,6 +562,8 @@ struct intel_gen6_power_mgmt {
562 u8 cur_delay; 562 u8 cur_delay;
563 u8 min_delay; 563 u8 min_delay;
564 u8 max_delay; 564 u8 max_delay;
565
566 struct delayed_work delayed_resume_work;
565}; 567};
566 568
567struct intel_ilk_power_mgmt { 569struct intel_ilk_power_mgmt {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index b6d980b0ac4c..169b416430db 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3304,23 +3304,46 @@ static void intel_init_emon(struct drm_device *dev)
3304 3304
3305void intel_disable_gt_powersave(struct drm_device *dev) 3305void intel_disable_gt_powersave(struct drm_device *dev)
3306{ 3306{
3307 struct drm_i915_private *dev_priv = dev->dev_private;
3308
3307 if (IS_IRONLAKE_M(dev)) { 3309 if (IS_IRONLAKE_M(dev)) {
3308 ironlake_disable_drps(dev); 3310 ironlake_disable_drps(dev);
3309 ironlake_disable_rc6(dev); 3311 ironlake_disable_rc6(dev);
3310 } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { 3312 } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) {
3313 cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
3311 gen6_disable_rps(dev); 3314 gen6_disable_rps(dev);
3312 } 3315 }
3313} 3316}
3314 3317
3318static void intel_gen6_powersave_work(struct work_struct *work)
3319{
3320 struct drm_i915_private *dev_priv =
3321 container_of(work, struct drm_i915_private,
3322 rps.delayed_resume_work.work);
3323 struct drm_device *dev = dev_priv->dev;
3324
3325 mutex_lock(&dev->struct_mutex);
3326 gen6_enable_rps(dev);
3327 gen6_update_ring_freq(dev);
3328 mutex_unlock(&dev->struct_mutex);
3329}
3330
3315void intel_enable_gt_powersave(struct drm_device *dev) 3331void intel_enable_gt_powersave(struct drm_device *dev)
3316{ 3332{
3333 struct drm_i915_private *dev_priv = dev->dev_private;
3334
3317 if (IS_IRONLAKE_M(dev)) { 3335 if (IS_IRONLAKE_M(dev)) {
3318 ironlake_enable_drps(dev); 3336 ironlake_enable_drps(dev);
3319 ironlake_enable_rc6(dev); 3337 ironlake_enable_rc6(dev);
3320 intel_init_emon(dev); 3338 intel_init_emon(dev);
3321 } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { 3339 } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
3322 gen6_enable_rps(dev); 3340 /*
3323 gen6_update_ring_freq(dev); 3341 * PCU communication is slow and this doesn't need to be
3342 * done at any specific time, so do this out of our fast path
3343 * to make resume and init faster.
3344 */
3345 schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
3346 round_jiffies_up_relative(HZ));
3324 } 3347 }
3325} 3348}
3326 3349
@@ -4216,6 +4239,8 @@ void intel_gt_init(struct drm_device *dev)
4216 dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; 4239 dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
4217 dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; 4240 dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
4218 } 4241 }
4242 INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
4243 intel_gen6_powersave_work);
4219} 4244}
4220 4245
4221int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val) 4246int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val)