Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c117aa4d authored by Rob Herring's avatar Rob Herring
Browse files

drm: Add a drm_gem_objects_lookup helper



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 <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <maxime.ripard@bootlin.com>
Cc: Sean Paul <sean@poorly.run>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Acked-by: default avatarAlyssa Rosenzweig <alyssa@rosenzweig.io>
Acked-by: default avatarTomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: default avatarRob Herring <robh@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190409205427.6943-3-robh@kernel.org
parent d08d42de
Loading
Loading
Loading
Loading
+83 −10
Original line number Diff line number Diff line
@@ -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
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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);