]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm: Add a drm_gem_objects_lookup helper
authorRob Herring <robh@kernel.org>
Fri, 8 Mar 2019 20:26:02 +0000 (14:26 -0600)
committerRob Herring <robh@kernel.org>
Fri, 12 Apr 2019 17:53:58 +0000 (12:53 -0500)
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: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Acked-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190409205427.6943-3-robh@kernel.org
drivers/gpu/drm/drm_gem.c
include/drm/drm_gem.h

index 52c0a837a3b23693ab72fbb1767216a20ca18e03..e93043b64c2d6798f7c744cc930546f7eef8881f 100644 (file)
@@ -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);
index 2955aaab3dca0e7e4a6031ca5082a393a0de33df..5ee85c9eaa9dbdc6ac9bc3e0bb7fb289027c45c7 100644 (file)
@@ -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);