--- x/drivers/gpu/drm/drm_gem.c +++ y/drivers/gpu/drm/drm_gem.c @@ -404,7 +404,8 @@ drm_gem_handle_delete(struct drm_file *f spin_lock(&filp->table_lock); /* Check if we currently have a reference on the object */ - obj = idr_replace(&filp->object_idr, NULL, handle); + obj = idr_find(&filp->object_idr, handle); + idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); if (IS_ERR_OR_NULL(obj)) return -EINVAL; @@ -412,11 +413,6 @@ drm_gem_handle_delete(struct drm_file *f /* Release driver's reference and decrement refcount. */ drm_gem_object_release_handle(handle, obj, filp); - /* And finally make the handle available for future allocations. */ - spin_lock(&filp->table_lock); - idr_remove(&filp->object_idr, handle); - spin_unlock(&filp->table_lock); - return 0; } EXPORT_SYMBOL(drm_gem_handle_delete); @@ -1085,9 +1081,23 @@ drm_gem_open(struct drm_device *dev, str void drm_gem_release(struct drm_device *dev, struct drm_file *file_private) { - idr_for_each(&file_private->object_idr, - &drm_gem_object_release_handle, file_private); + struct drm_gem_object *obj; + int id; + + mutex_lock(&file_private->prime.lock); + for (;;) { + id = 0; + spin_lock(&file_private->table_lock); + obj = idr_get_next(&file_private->object_idr, &id); + if (obj) + idr_remove(&file_private->object_idr, id); + spin_unlock(&file_private->table_lock); + if (!obj) + break; + drm_gem_object_release_handle(id, obj, file_private); + } idr_destroy(&file_private->object_idr); + mutex_unlock(&file_private->prime.lock); } /**