aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-10-16 06:50:01 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-16 13:42:14 -0400
commit45c5f2022c798b2938d4c0d1c14795787f610ccd (patch)
treedf020d2a6734d4befeb4b860fc10d90f15be917d /drivers/gpu/drm
parent9514ac6e7a55328b1fad4b7fc7227d3beb01d7ad (diff)
drm/i915: Disable all GEM timers and work on unload
We have two once very similar functions, i915_gpu_idle() and i915_gem_idle(). The former is used as the lower level operation to flush work on the GPU, whereas the latter is the high level interface to flush the GEM bookkeeping in addition to flushing the GPU. As such i915_gem_idle() also clears out the request and activity lists and cancels the delayed work. This is what we need for unloading the driver, unfortunately we called i915_gpu_idle() instead. In the process, make sure that when cancelling the delayed work and timer, which is synchronous, that we do not hold any locks to prevent a deadlock if the work item is already waiting upon the mutex. This requires us to push the mutex down from the caller to i915_gem_idle(). v2: s/i915_gem_idle/i915_gem_suspend/ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70334 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Tested-by: xunx.fang@intel.com [danvet: Only set ums.suspended for !kms as discussed earlier. Chris noticed that this slipped through.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c8
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c4
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c45
4 files changed, 23 insertions, 36 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 9f71bc204e38..437886641d90 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1732,15 +1732,9 @@ int i915_driver_unload(struct drm_device *dev)
1732 if (dev_priv->mm.inactive_shrinker.scan_objects) 1732 if (dev_priv->mm.inactive_shrinker.scan_objects)
1733 unregister_shrinker(&dev_priv->mm.inactive_shrinker); 1733 unregister_shrinker(&dev_priv->mm.inactive_shrinker);
1734 1734
1735 mutex_lock(&dev->struct_mutex); 1735 ret = i915_gem_suspend(dev);
1736 ret = i915_gpu_idle(dev);
1737 if (ret) 1736 if (ret)
1738 DRM_ERROR("failed to idle hardware: %d\n", ret); 1737 DRM_ERROR("failed to idle hardware: %d\n", ret);
1739 i915_gem_retire_requests(dev);
1740 mutex_unlock(&dev->struct_mutex);
1741
1742 /* Cancel the retire work handler, which should be idle now. */
1743 cancel_delayed_work_sync(&dev_priv->mm.retire_work);
1744 1738
1745 io_mapping_free(dev_priv->gtt.mappable); 1739 io_mapping_free(dev_priv->gtt.mappable);
1746 arch_phys_wc_del(dev_priv->gtt.mtrr); 1740 arch_phys_wc_del(dev_priv->gtt.mtrr);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e9dfadca2d71..1060a96d2184 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -487,9 +487,7 @@ static int i915_drm_freeze(struct drm_device *dev)
487 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 487 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
488 int error; 488 int error;
489 489
490 mutex_lock(&dev->struct_mutex); 490 error = i915_gem_suspend(dev);
491 error = i915_gem_idle(dev);
492 mutex_unlock(&dev->struct_mutex);
493 if (error) { 491 if (error) {
494 dev_err(&dev->pdev->dev, 492 dev_err(&dev->pdev->dev,
495 "GEM idle failed, resume might fail\n"); 493 "GEM idle failed, resume might fail\n");
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b39a548f6a3c..e2bf930c2e91 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2037,7 +2037,7 @@ int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice);
2037void i915_gem_init_swizzling(struct drm_device *dev); 2037void i915_gem_init_swizzling(struct drm_device *dev);
2038void i915_gem_cleanup_ringbuffer(struct drm_device *dev); 2038void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
2039int __must_check i915_gpu_idle(struct drm_device *dev); 2039int __must_check i915_gpu_idle(struct drm_device *dev);
2040int __must_check i915_gem_idle(struct drm_device *dev); 2040int __must_check i915_gem_suspend(struct drm_device *dev);
2041int __i915_add_request(struct intel_ring_buffer *ring, 2041int __i915_add_request(struct intel_ring_buffer *ring,
2042 struct drm_file *file, 2042 struct drm_file *file,
2043 struct drm_i915_gem_object *batch_obj, 2043 struct drm_i915_gem_object *batch_obj,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1d22c99601ed..f10ae6498bce 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4265,17 +4265,18 @@ void i915_gem_vma_destroy(struct i915_vma *vma)
4265} 4265}
4266 4266
4267int 4267int
4268i915_gem_idle(struct drm_device *dev) 4268i915_gem_suspend(struct drm_device *dev)
4269{ 4269{
4270 drm_i915_private_t *dev_priv = dev->dev_private; 4270 drm_i915_private_t *dev_priv = dev->dev_private;
4271 int ret; 4271 int ret = 0;
4272 4272
4273 mutex_lock(&dev->struct_mutex);
4273 if (dev_priv->ums.mm_suspended) 4274 if (dev_priv->ums.mm_suspended)
4274 return 0; 4275 goto err;
4275 4276
4276 ret = i915_gpu_idle(dev); 4277 ret = i915_gpu_idle(dev);
4277 if (ret) 4278 if (ret)
4278 return ret; 4279 goto err;
4279 4280
4280 i915_gem_retire_requests(dev); 4281 i915_gem_retire_requests(dev);
4281 4282
@@ -4283,16 +4284,26 @@ i915_gem_idle(struct drm_device *dev)
4283 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 4284 if (!drm_core_check_feature(dev, DRIVER_MODESET))
4284 i915_gem_evict_everything(dev); 4285 i915_gem_evict_everything(dev);
4285 4286
4286 del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
4287
4288 i915_kernel_lost_context(dev); 4287 i915_kernel_lost_context(dev);
4289 i915_gem_cleanup_ringbuffer(dev); 4288 i915_gem_cleanup_ringbuffer(dev);
4290 4289
4291 /* Cancel the retire work handler, which should be idle now. */ 4290 /* Hack! Don't let anybody do execbuf while we don't control the chip.
4291 * We need to replace this with a semaphore, or something.
4292 * And not confound ums.mm_suspended!
4293 */
4294 dev_priv->ums.mm_suspended = !drm_core_check_feature(dev,
4295 DRIVER_MODESET);
4296 mutex_unlock(&dev->struct_mutex);
4297
4298 del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
4292 cancel_delayed_work_sync(&dev_priv->mm.retire_work); 4299 cancel_delayed_work_sync(&dev_priv->mm.retire_work);
4293 cancel_delayed_work_sync(&dev_priv->mm.idle_work); 4300 cancel_delayed_work_sync(&dev_priv->mm.idle_work);
4294 4301
4295 return 0; 4302 return 0;
4303
4304err:
4305 mutex_unlock(&dev->struct_mutex);
4306 return ret;
4296} 4307}
4297 4308
4298int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice) 4309int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice)
@@ -4545,26 +4556,12 @@ int
4545i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, 4556i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
4546 struct drm_file *file_priv) 4557 struct drm_file *file_priv)
4547{ 4558{
4548 struct drm_i915_private *dev_priv = dev->dev_private;
4549 int ret;
4550
4551 if (drm_core_check_feature(dev, DRIVER_MODESET)) 4559 if (drm_core_check_feature(dev, DRIVER_MODESET))
4552 return 0; 4560 return 0;
4553 4561
4554 drm_irq_uninstall(dev); 4562 drm_irq_uninstall(dev);
4555 4563
4556 mutex_lock(&dev->struct_mutex); 4564 return i915_gem_suspend(dev);
4557 ret = i915_gem_idle(dev);
4558
4559 /* Hack! Don't let anybody do execbuf while we don't control the chip.
4560 * We need to replace this with a semaphore, or something.
4561 * And not confound ums.mm_suspended!
4562 */
4563 if (ret != 0)
4564 dev_priv->ums.mm_suspended = 1;
4565 mutex_unlock(&dev->struct_mutex);
4566
4567 return ret;
4568} 4565}
4569 4566
4570void 4567void
@@ -4575,11 +4572,9 @@ i915_gem_lastclose(struct drm_device *dev)
4575 if (drm_core_check_feature(dev, DRIVER_MODESET)) 4572 if (drm_core_check_feature(dev, DRIVER_MODESET))
4576 return; 4573 return;
4577 4574
4578 mutex_lock(&dev->struct_mutex); 4575 ret = i915_gem_suspend(dev);
4579 ret = i915_gem_idle(dev);
4580 if (ret) 4576 if (ret)
4581 DRM_ERROR("failed to idle hardware: %d\n", ret); 4577 DRM_ERROR("failed to idle hardware: %d\n", ret);
4582 mutex_unlock(&dev->struct_mutex);
4583} 4578}
4584 4579
4585static void 4580static void