diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 891c3bff5ae0..ee9939356de4 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -1073,6 +1073,30 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private) spin_lock_init(&file_private->table_lock); } +struct drm_gem_object_entry { + struct drm_gem_object *obj; + struct list_head head; +}; + +static int drm_gem_object_collect(int id, void *ptr, void *data) +{ + struct drm_gem_object_entry *entry; + struct drm_gem_object *obj = ptr; + struct list_head *list = data; + + if (!obj) + return 0; + + entry = kmalloc_obj(*entry, GFP_ATOMIC); + if (!entry) + return -ENOMEM; + + drm_gem_object_get(obj); + entry->obj = obj; + list_add(&entry->head, list); + return 0; +} + /** * drm_gem_release - release file-private GEM resources * @dev: drm_device which is being closed by userspace @@ -1085,8 +1109,21 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private) void drm_gem_release(struct drm_device *dev, struct drm_file *file_private) { + struct drm_gem_object_entry *entry, *tmp; + LIST_HEAD(list); + + spin_lock(&file_private->table_lock); idr_for_each(&file_private->object_idr, - &drm_gem_object_release_handle, file_private); + &drm_gem_object_collect, &list); + spin_unlock(&file_private->table_lock); + + list_for_each_entry_safe(entry, tmp, &list, head) { + list_del(&entry->head); + drm_gem_object_release_handle(0, entry->obj, file_private); + drm_gem_object_put(entry->obj); + kfree(entry); + } + idr_destroy(&file_private->object_idr); }