diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-10-16 06:50:01 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-10-16 13:42:14 -0400 |
commit | 45c5f2022c798b2938d4c0d1c14795787f610ccd (patch) | |
tree | df020d2a6734d4befeb4b860fc10d90f15be917d /drivers/gpu/drm | |
parent | 9514ac6e7a55328b1fad4b7fc7227d3beb01d7ad (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.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 45 |
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); | |||
2037 | void i915_gem_init_swizzling(struct drm_device *dev); | 2037 | void i915_gem_init_swizzling(struct drm_device *dev); |
2038 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); | 2038 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); |
2039 | int __must_check i915_gpu_idle(struct drm_device *dev); | 2039 | int __must_check i915_gpu_idle(struct drm_device *dev); |
2040 | int __must_check i915_gem_idle(struct drm_device *dev); | 2040 | int __must_check i915_gem_suspend(struct drm_device *dev); |
2041 | int __i915_add_request(struct intel_ring_buffer *ring, | 2041 | int __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 | ||
4267 | int | 4267 | int |
4268 | i915_gem_idle(struct drm_device *dev) | 4268 | i915_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 | |||
4304 | err: | ||
4305 | mutex_unlock(&dev->struct_mutex); | ||
4306 | return ret; | ||
4296 | } | 4307 | } |
4297 | 4308 | ||
4298 | int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice) | 4309 | int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice) |
@@ -4545,26 +4556,12 @@ int | |||
4545 | i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, | 4556 | i915_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 | ||
4570 | void | 4567 | void |
@@ -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 | ||
4585 | static void | 4580 | static void |