Skip to content

Commit

Permalink
drm: Add a drm_gem_objects_lookup helper
Browse files Browse the repository at this point in the history
Similar to the single handle drm_gem_object_lookup(),
drm_gem_objects_lookup() takes an array of handles and returns an array
of GEM objects.

v2:
- Take the userspace pointer directly and allocate the array.
- Expand the function documentation.

Cc: Maarten Lankhorst <[email protected]>
Cc: Maxime Ripard <[email protected]>
Cc: Sean Paul <[email protected]>
Cc: David Airlie <[email protected]>
Cc: Daniel Vetter <[email protected]>
Acked-by: Alyssa Rosenzweig <[email protected]>
Acked-by: Tomeu Vizoso <[email protected]>
Signed-off-by: Rob Herring <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
  • Loading branch information
robherring committed Apr 12, 2019
1 parent d08d42d commit c117aa4
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 10 deletions.
93 changes: 83 additions & 10 deletions drivers/gpu/drm/drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,85 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
}
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;
struct drm_gem_object *obj;

spin_lock(&filp->table_lock);

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;
}
drm_gem_object_get(obj);
objs[i] = obj;
}
spin_unlock(&filp->table_lock);

return ret;
}

/**
* drm_gem_objects_lookup - look up GEM objects from an array of handles
* @filp: DRM file private date
* @bo_handles: user pointer to array of userspace handle
* @count: size of handle array
* @objs_out: returned pointer to array of drm_gem_object pointers
*
* Takes an array of userspace handles and returns a newly allocated array of
* GEM objects.
*
* For a single handle lookup, use drm_gem_object_lookup().
*
* Returns:
*
* @objs filled in with GEM object pointers. Returned GEM objects need to be
* released with drm_gem_object_put(). -ENOENT is returned on a lookup
* failure. 0 is returned on success.
*
*/
int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
int count, struct drm_gem_object ***objs_out)
{
int ret;
u32 *handles;
struct drm_gem_object **objs;

if (!count)
return 0;

objs = kvmalloc_array(count, sizeof(struct drm_gem_object *),
GFP_KERNEL | __GFP_ZERO);
if (!objs)
return -ENOMEM;

handles = kvmalloc_array(count, sizeof(u32), GFP_KERNEL);
if (!handles) {
ret = -ENOMEM;
goto out;
}

if (copy_from_user(handles, bo_handles, count * sizeof(u32))) {
ret = -EFAULT;
DRM_DEBUG("Failed to copy in GEM handles\n");
goto out;
}

ret = objects_lookup(filp, handles, count, objs);
*objs_out = objs;

out:
kvfree(handles);
return ret;

}
EXPORT_SYMBOL(drm_gem_objects_lookup);

/**
* drm_gem_object_lookup - look up a GEM object from its handle
* @filp: DRM file private date
Expand All @@ -655,21 +734,15 @@ EXPORT_SYMBOL(drm_gem_put_pages);
*
* A reference to the object named by the handle if such exists on @filp, NULL
* otherwise.
*
* If looking up an array of handles, use drm_gem_objects_lookup().
*/
struct drm_gem_object *
drm_gem_object_lookup(struct drm_file *filp, u32 handle)
{
struct drm_gem_object *obj;

spin_lock(&filp->table_lock);

/* Check if we currently have a reference on the object */
obj = idr_find(&filp->object_idr, handle);
if (obj)
drm_gem_object_get(obj);

spin_unlock(&filp->table_lock);
struct drm_gem_object *obj = NULL;

objects_lookup(filp, &handle, 1, &obj);
return obj;
}
EXPORT_SYMBOL(drm_gem_object_lookup);
Expand Down
2 changes: 2 additions & 0 deletions include/drm/drm_gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj);
void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
bool dirty, bool accessed);

int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
int count, struct drm_gem_object ***objs_out);
struct drm_gem_object *drm_gem_object_lookup(struct drm_file *filp, u32 handle);
long drm_gem_reservation_object_wait(struct drm_file *filep, u32 handle,
bool wait_all, unsigned long timeout);
Expand Down

0 comments on commit c117aa4

Please sign in to comment.