diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 51 |
2 files changed, 49 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a27780b7aef2..906663b9929e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -552,6 +552,14 @@ typedef struct drm_i915_private { | |||
552 | struct list_head fence_list; | 552 | struct list_head fence_list; |
553 | 553 | ||
554 | /** | 554 | /** |
555 | * List of objects currently pending being freed. | ||
556 | * | ||
557 | * These objects are no longer in use, but due to a signal | ||
558 | * we were prevented from freeing them at the appointed time. | ||
559 | */ | ||
560 | struct list_head deferred_free_list; | ||
561 | |||
562 | /** | ||
555 | * We leave the user IRQ off as much as possible, | 563 | * We leave the user IRQ off as much as possible, |
556 | * but this means that requests will finish and never | 564 | * but this means that requests will finish and never |
557 | * be retired once the system goes idle. Set a timer to | 565 | * be retired once the system goes idle. Set a timer to |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 138ca6ea5ef7..f45f385c84cd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -53,6 +53,7 @@ static int i915_gem_evict_from_inactive_list(struct drm_device *dev); | |||
53 | static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | 53 | static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, |
54 | struct drm_i915_gem_pwrite *args, | 54 | struct drm_i915_gem_pwrite *args, |
55 | struct drm_file *file_priv); | 55 | struct drm_file *file_priv); |
56 | static void i915_gem_free_object_tail(struct drm_gem_object *obj); | ||
56 | 57 | ||
57 | static LIST_HEAD(shrink_list); | 58 | static LIST_HEAD(shrink_list); |
58 | static DEFINE_SPINLOCK(shrink_list_lock); | 59 | static DEFINE_SPINLOCK(shrink_list_lock); |
@@ -1755,6 +1756,20 @@ i915_gem_retire_requests(struct drm_device *dev) | |||
1755 | { | 1756 | { |
1756 | drm_i915_private_t *dev_priv = dev->dev_private; | 1757 | drm_i915_private_t *dev_priv = dev->dev_private; |
1757 | 1758 | ||
1759 | if (!list_empty(&dev_priv->mm.deferred_free_list)) { | ||
1760 | struct drm_i915_gem_object *obj_priv, *tmp; | ||
1761 | |||
1762 | /* We must be careful that during unbind() we do not | ||
1763 | * accidentally infinitely recurse into retire requests. | ||
1764 | * Currently: | ||
1765 | * retire -> free -> unbind -> wait -> retire_ring | ||
1766 | */ | ||
1767 | list_for_each_entry_safe(obj_priv, tmp, | ||
1768 | &dev_priv->mm.deferred_free_list, | ||
1769 | list) | ||
1770 | i915_gem_free_object_tail(&obj_priv->base); | ||
1771 | } | ||
1772 | |||
1758 | i915_gem_retire_requests_ring(dev, &dev_priv->render_ring); | 1773 | i915_gem_retire_requests_ring(dev, &dev_priv->render_ring); |
1759 | if (HAS_BSD(dev)) | 1774 | if (HAS_BSD(dev)) |
1760 | i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); | 1775 | i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); |
@@ -4458,20 +4473,19 @@ int i915_gem_init_object(struct drm_gem_object *obj) | |||
4458 | return 0; | 4473 | return 0; |
4459 | } | 4474 | } |
4460 | 4475 | ||
4461 | void i915_gem_free_object(struct drm_gem_object *obj) | 4476 | static void i915_gem_free_object_tail(struct drm_gem_object *obj) |
4462 | { | 4477 | { |
4463 | struct drm_device *dev = obj->dev; | 4478 | struct drm_device *dev = obj->dev; |
4479 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
4464 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 4480 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
4481 | int ret; | ||
4465 | 4482 | ||
4466 | trace_i915_gem_object_destroy(obj); | 4483 | ret = i915_gem_object_unbind(obj); |
4467 | 4484 | if (ret == -ERESTARTSYS) { | |
4468 | while (obj_priv->pin_count > 0) | 4485 | list_move(&obj_priv->list, |
4469 | i915_gem_object_unpin(obj); | 4486 | &dev_priv->mm.deferred_free_list); |
4470 | 4487 | return; | |
4471 | if (obj_priv->phys_obj) | 4488 | } |
4472 | i915_gem_detach_phys_object(dev, obj); | ||
4473 | |||
4474 | i915_gem_object_unbind(obj); | ||
4475 | 4489 | ||
4476 | if (obj_priv->mmap_offset) | 4490 | if (obj_priv->mmap_offset) |
4477 | i915_gem_free_mmap_offset(obj); | 4491 | i915_gem_free_mmap_offset(obj); |
@@ -4483,6 +4497,22 @@ void i915_gem_free_object(struct drm_gem_object *obj) | |||
4483 | kfree(obj_priv); | 4497 | kfree(obj_priv); |
4484 | } | 4498 | } |
4485 | 4499 | ||
4500 | void i915_gem_free_object(struct drm_gem_object *obj) | ||
4501 | { | ||
4502 | struct drm_device *dev = obj->dev; | ||
4503 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | ||
4504 | |||
4505 | trace_i915_gem_object_destroy(obj); | ||
4506 | |||
4507 | while (obj_priv->pin_count > 0) | ||
4508 | i915_gem_object_unpin(obj); | ||
4509 | |||
4510 | if (obj_priv->phys_obj) | ||
4511 | i915_gem_detach_phys_object(dev, obj); | ||
4512 | |||
4513 | i915_gem_free_object_tail(obj); | ||
4514 | } | ||
4515 | |||
4486 | /** Unbinds all inactive objects. */ | 4516 | /** Unbinds all inactive objects. */ |
4487 | static int | 4517 | static int |
4488 | i915_gem_evict_from_inactive_list(struct drm_device *dev) | 4518 | i915_gem_evict_from_inactive_list(struct drm_device *dev) |
@@ -4756,6 +4786,7 @@ i915_gem_load(struct drm_device *dev) | |||
4756 | INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); | 4786 | INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); |
4757 | INIT_LIST_HEAD(&dev_priv->mm.inactive_list); | 4787 | INIT_LIST_HEAD(&dev_priv->mm.inactive_list); |
4758 | INIT_LIST_HEAD(&dev_priv->mm.fence_list); | 4788 | INIT_LIST_HEAD(&dev_priv->mm.fence_list); |
4789 | INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list); | ||
4759 | INIT_LIST_HEAD(&dev_priv->render_ring.active_list); | 4790 | INIT_LIST_HEAD(&dev_priv->render_ring.active_list); |
4760 | INIT_LIST_HEAD(&dev_priv->render_ring.request_list); | 4791 | INIT_LIST_HEAD(&dev_priv->render_ring.request_list); |
4761 | if (HAS_BSD(dev)) { | 4792 | if (HAS_BSD(dev)) { |