aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-08-26 08:46:09 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-01 01:45:13 -0400
commitaec347ab197ec064d1e98b52717d968521a62929 (patch)
tree3eeb62348f932e634a9d9f855121f72af1a6c65d
parent45f80d53b1fe2f68c6c5b2b4518b67278bcde805 (diff)
drm/i915: Delay the release of the forcewake by a jiffie
Obtaining the forcwake requires expensive and time consuming serialisation. And we often try to obtain the forcewake multiple times in very quick succession. We can reduce the overhead of these sequences by delaying the forcewake release, and so not hammer the hw quite so hard. I was hoping this would help with the spurious [drm:__gen6_gt_force_wake_mt_get] *ERROR* Timed out waiting for forcewake old ack to clear. found on Haswell. Alas not. v2: Fix teardown ordering - unmap the regs after turning off forcewake, and make sure we do turn off forcewake - both found by Ville. v3: As we introduce intel_uncore_fini(), use it to make sure everything is disabled before we hand back to the BIOS. Note: I have no claims for improved performance, stablity or power comsumption for this patch. We should not be hitting the registers often enough for this to improve benchmarks, but given the nature of our hw it is likely to improve long term stability. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h3
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c33
3 files changed, 38 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index a71bb127e261..d35de1b9a2dd 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1792,8 +1792,6 @@ int i915_driver_unload(struct drm_device *dev)
1792 list_del(&dev_priv->gtt.base.global_link); 1792 list_del(&dev_priv->gtt.base.global_link);
1793 WARN_ON(!list_empty(&dev_priv->vm_list)); 1793 WARN_ON(!list_empty(&dev_priv->vm_list));
1794 drm_mm_takedown(&dev_priv->gtt.base.mm); 1794 drm_mm_takedown(&dev_priv->gtt.base.mm);
1795 if (dev_priv->regs != NULL)
1796 pci_iounmap(dev->pdev, dev_priv->regs);
1797 1795
1798 intel_teardown_gmbus(dev); 1796 intel_teardown_gmbus(dev);
1799 intel_teardown_mchbar(dev); 1797 intel_teardown_mchbar(dev);
@@ -1803,6 +1801,10 @@ int i915_driver_unload(struct drm_device *dev)
1803 1801
1804 dev_priv->gtt.base.cleanup(&dev_priv->gtt.base); 1802 dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
1805 1803
1804 intel_uncore_fini(dev);
1805 if (dev_priv->regs != NULL)
1806 pci_iounmap(dev->pdev, dev_priv->regs);
1807
1806 if (dev_priv->slab) 1808 if (dev_priv->slab)
1807 kmem_cache_destroy(dev_priv->slab); 1809 kmem_cache_destroy(dev_priv->slab);
1808 1810
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bbe889dfc0ff..662c0ff0b049 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -408,6 +408,8 @@ struct intel_uncore {
408 408
409 unsigned fifo_count; 409 unsigned fifo_count;
410 unsigned forcewake_count; 410 unsigned forcewake_count;
411
412 struct delayed_work force_wake_work;
411}; 413};
412 414
413#define DEV_INFO_FOR_EACH_FLAG(func, sep) \ 415#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
@@ -1801,6 +1803,7 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev);
1801extern void intel_uncore_init(struct drm_device *dev); 1803extern void intel_uncore_init(struct drm_device *dev);
1802extern void intel_uncore_clear_errors(struct drm_device *dev); 1804extern void intel_uncore_clear_errors(struct drm_device *dev);
1803extern void intel_uncore_check_errors(struct drm_device *dev); 1805extern void intel_uncore_check_errors(struct drm_device *dev);
1806extern void intel_uncore_fini(struct drm_device *dev);
1804 1807
1805void 1808void
1806i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); 1809i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 8649f1c36b00..f2753d9fb098 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -204,6 +204,18 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
204 gen6_gt_check_fifodbg(dev_priv); 204 gen6_gt_check_fifodbg(dev_priv);
205} 205}
206 206
207static void gen6_force_wake_work(struct work_struct *work)
208{
209 struct drm_i915_private *dev_priv =
210 container_of(work, typeof(*dev_priv), uncore.force_wake_work.work);
211 unsigned long irqflags;
212
213 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
214 if (--dev_priv->uncore.forcewake_count == 0)
215 dev_priv->uncore.funcs.force_wake_put(dev_priv);
216 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
217}
218
207void intel_uncore_early_sanitize(struct drm_device *dev) 219void intel_uncore_early_sanitize(struct drm_device *dev)
208{ 220{
209 struct drm_i915_private *dev_priv = dev->dev_private; 221 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -216,6 +228,9 @@ void intel_uncore_init(struct drm_device *dev)
216{ 228{
217 struct drm_i915_private *dev_priv = dev->dev_private; 229 struct drm_i915_private *dev_priv = dev->dev_private;
218 230
231 INIT_DELAYED_WORK(&dev_priv->uncore.force_wake_work,
232 gen6_force_wake_work);
233
219 if (IS_VALLEYVIEW(dev)) { 234 if (IS_VALLEYVIEW(dev)) {
220 dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get; 235 dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get;
221 dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put; 236 dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put;
@@ -261,6 +276,16 @@ void intel_uncore_init(struct drm_device *dev)
261 } 276 }
262} 277}
263 278
279void intel_uncore_fini(struct drm_device *dev)
280{
281 struct drm_i915_private *dev_priv = dev->dev_private;
282
283 flush_delayed_work(&dev_priv->uncore.force_wake_work);
284
285 /* Paranoia: make sure we have disabled everything before we exit. */
286 intel_uncore_sanitize(dev);
287}
288
264static void intel_uncore_forcewake_reset(struct drm_device *dev) 289static void intel_uncore_forcewake_reset(struct drm_device *dev)
265{ 290{
266 struct drm_i915_private *dev_priv = dev->dev_private; 291 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -306,8 +331,12 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
306 unsigned long irqflags; 331 unsigned long irqflags;
307 332
308 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 333 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
309 if (--dev_priv->uncore.forcewake_count == 0) 334 if (--dev_priv->uncore.forcewake_count == 0) {
310 dev_priv->uncore.funcs.force_wake_put(dev_priv); 335 dev_priv->uncore.forcewake_count++;
336 mod_delayed_work(dev_priv->wq,
337 &dev_priv->uncore.force_wake_work,
338 1);
339 }
311 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 340 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
312} 341}
313 342