summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_gem.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 7ff6b7bbeb73..c4a3de3b920e 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -783,7 +783,7 @@ EXPORT_SYMBOL(drm_gem_put_pages);
static int objects_lookup(struct drm_file *filp, u32 *handle, int count,
struct drm_gem_object **objs)
{
- int i, ret = 0;
+ int i;
struct drm_gem_object *obj;
spin_lock(&filp->table_lock);
@@ -791,16 +791,23 @@ static int objects_lookup(struct drm_file *filp, u32 *handle, int count,
for (i = 0; i < count; i++) {
/* Check if we currently have a reference on the object */
obj = idr_find(&filp->object_idr, handle[i]);
- if (!obj) {
- ret = -ENOENT;
- break;
- }
+ if (!obj)
+ goto err;
+
drm_gem_object_get(obj);
objs[i] = obj;
}
+
spin_unlock(&filp->table_lock);
+ return 0;
- return ret;
+err:
+ spin_unlock(&filp->table_lock);
+
+ while (i--)
+ drm_gem_object_put(objs[i]);
+
+ return -ENOENT;
}
/**
@@ -828,24 +835,34 @@ int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
u32 *handles;
int ret;
+ *objs_out = NULL;
+
if (!count)
return 0;
- objs = kvmalloc_array(count, sizeof(struct drm_gem_object *),
- GFP_KERNEL | __GFP_ZERO);
+ objs = kvmalloc_array(count, sizeof(*objs), GFP_KERNEL);
if (!objs)
return -ENOMEM;
- *objs_out = objs;
-
handles = vmemdup_array_user(bo_handles, count, sizeof(u32));
- if (IS_ERR(handles))
- return PTR_ERR(handles);
+ if (IS_ERR(handles)) {
+ ret = PTR_ERR(handles);
+ goto err_free_objs;
+ }
ret = objects_lookup(filp, handles, count, objs);
+ if (ret)
+ goto err_free_handles;
+
kvfree(handles);
- return ret;
+ *objs_out = objs;
+ return 0;
+err_free_handles:
+ kvfree(handles);
+err_free_objs:
+ kvfree(objs);
+ return ret;
}
EXPORT_SYMBOL(drm_gem_objects_lookup);