--- x/drivers/gpu/drm/drm_gem.c +++ y/drivers/gpu/drm/drm_gem.c @@ -387,6 +387,24 @@ drm_gem_object_release_handle(int id, vo return 0; } +static int +drm_gem_object_release_idr_handle(int id, void *ptr, void *data) +{ + struct drm_file *filp = data; + struct drm_gem_object *obj, *tmp = ptr; + + spin_lock(&filp->table_lock); + obj = idr_replace(&filp->object_idr, NULL, id); + idr_remove(&filp->object_idr, id); + spin_unlock(&filp->table_lock); + if (IS_ERR_OR_NULL(obj)) + return 0; + if (obj != tmp) + return 0; + drm_gem_object_release_handle(id, obj, filp); + return 0; +} + /** * drm_gem_handle_delete - deletes the given file-private handle * @filp: drm file-private structure to use for the handle look up @@ -405,6 +423,7 @@ drm_gem_handle_delete(struct drm_file *f /* Check if we currently have a reference on the object */ obj = idr_replace(&filp->object_idr, NULL, handle); + idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); if (IS_ERR_OR_NULL(obj)) return -EINVAL; @@ -412,11 +431,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); @@ -1086,7 +1100,7 @@ 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); + &drm_gem_object_release_idr_handle, file_private); idr_destroy(&file_private->object_idr); }