aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-09-03 14:23:37 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-09-04 03:56:07 -0400
commit4ad72b7fadd285f849439cdbc408f8b847cef704 (patch)
treeeabc1578fbc3ade244c77c19f90294991717b324 /drivers/gpu/drm
parent8fe8a3feeb5aedd17f7b09e51b60b38a6ba7005f (diff)
drm/i915: Fix unsafe vma iteration in i915_drop_caches
When unbinding, there is a possibility that we drop the active reference on the object, thereby freeing it. If that happens, we may destroy the vm link as well as the object and vma. So iterate carefully. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d8389b2dcd77..c19fbdc1430b 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3812,8 +3812,6 @@ i915_drop_caches_set(void *data, u64 val)
3812 struct drm_device *dev = data; 3812 struct drm_device *dev = data;
3813 struct drm_i915_private *dev_priv = dev->dev_private; 3813 struct drm_i915_private *dev_priv = dev->dev_private;
3814 struct drm_i915_gem_object *obj, *next; 3814 struct drm_i915_gem_object *obj, *next;
3815 struct i915_address_space *vm;
3816 struct i915_vma *vma, *x;
3817 int ret; 3815 int ret;
3818 3816
3819 DRM_DEBUG("Dropping caches: 0x%08llx\n", val); 3817 DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
@@ -3834,16 +3832,23 @@ i915_drop_caches_set(void *data, u64 val)
3834 i915_gem_retire_requests(dev); 3832 i915_gem_retire_requests(dev);
3835 3833
3836 if (val & DROP_BOUND) { 3834 if (val & DROP_BOUND) {
3837 list_for_each_entry(vm, &dev_priv->vm_list, global_link) { 3835 list_for_each_entry_safe(obj, next, &dev_priv->mm.bound_list,
3838 list_for_each_entry_safe(vma, x, &vm->inactive_list, 3836 global_list) {
3839 mm_list) { 3837 struct i915_vma *vma, *v;
3838
3839 ret = 0;
3840 drm_gem_object_reference(&obj->base);
3841 list_for_each_entry_safe(vma, v, &obj->vma_list, vma_link) {
3840 if (vma->pin_count) 3842 if (vma->pin_count)
3841 continue; 3843 continue;
3842 3844
3843 ret = i915_vma_unbind(vma); 3845 ret = i915_vma_unbind(vma);
3844 if (ret) 3846 if (ret)
3845 goto unlock; 3847 break;
3846 } 3848 }
3849 drm_gem_object_unreference(&obj->base);
3850 if (ret)
3851 goto unlock;
3847 } 3852 }
3848 } 3853 }
3849 3854