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>
This commit is contained in:
parent
8fe8a3feeb
commit
4ad72b7fad
|
@ -3812,8 +3812,6 @@ i915_drop_caches_set(void *data, u64 val)
|
|||
struct drm_device *dev = data;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj, *next;
|
||||
struct i915_address_space *vm;
|
||||
struct i915_vma *vma, *x;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
|
||||
|
@ -3834,16 +3832,23 @@ i915_drop_caches_set(void *data, u64 val)
|
|||
i915_gem_retire_requests(dev);
|
||||
|
||||
if (val & DROP_BOUND) {
|
||||
list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
|
||||
list_for_each_entry_safe(vma, x, &vm->inactive_list,
|
||||
mm_list) {
|
||||
list_for_each_entry_safe(obj, next, &dev_priv->mm.bound_list,
|
||||
global_list) {
|
||||
struct i915_vma *vma, *v;
|
||||
|
||||
ret = 0;
|
||||
drm_gem_object_reference(&obj->base);
|
||||
list_for_each_entry_safe(vma, v, &obj->vma_list, vma_link) {
|
||||
if (vma->pin_count)
|
||||
continue;
|
||||
|
||||
ret = i915_vma_unbind(vma);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
break;
|
||||
}
|
||||
drm_gem_object_unreference(&obj->base);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue