aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h8
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c51
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);
53static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, 53static 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);
56static void i915_gem_free_object_tail(struct drm_gem_object *obj);
56 57
57static LIST_HEAD(shrink_list); 58static LIST_HEAD(shrink_list);
58static DEFINE_SPINLOCK(shrink_list_lock); 59static 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
4461void i915_gem_free_object(struct drm_gem_object *obj) 4476static 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
4500void 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. */
4487static int 4517static int
4488i915_gem_evict_from_inactive_list(struct drm_device *dev) 4518i915_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)) {