[PATCH 1/5] drm: introduce sync objects (v3)

Jason Ekstrand jason at jlekstrand.net
Wed May 24 17:34:09 UTC 2017


I can't really review for all of the kernel details (though the seem ok to
me) so this mostly applies to the API:

Reviewed-by: Jason Ekstrand <jason at jlekstrand.net>

On Wed, May 24, 2017 at 12:06 AM, Dave Airlie <airlied at gmail.com> wrote:

> From: Dave Airlie <airlied at redhat.com>
>
> Sync objects are new toplevel drm object, that contain a
> pointer to a fence. This fence can be updated via command
> submission ioctls via drivers.
>
> There is also a generic wait obj API modelled on the vulkan
> wait API (with code modelled on some amdgpu code).
>
> These objects can be converted to an opaque fd that can be
> passes between processes.
>
> v2: rename reference/unreference to put/get (Chris)
> fix leaked reference (David Zhou)
> drop mutex in favour of cmpxchg (Chris)
> v3: cleanups from danvet, rebase on drm_fops rename
> check fd_flags is 0 in ioctls.
>
> Reviewed-by: Sean Paul <seanpaul at chromium.org>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  Documentation/gpu/drm-internals.rst |   3 +
>  Documentation/gpu/drm-mm.rst        |  12 ++
>  drivers/gpu/drm/Makefile            |   2 +-
>  drivers/gpu/drm/drm_file.c          |   8 +
>  drivers/gpu/drm/drm_internal.h      |  13 ++
>  drivers/gpu/drm/drm_ioctl.c         |  12 ++
>  drivers/gpu/drm/drm_syncobj.c       | 377 ++++++++++++++++++++++++++++++
> ++++++
>  include/drm/drmP.h                  |   1 -
>  include/drm/drm_drv.h               |   1 +
>  include/drm/drm_file.h              |   5 +
>  include/drm/drm_syncobj.h           |  87 +++++++++
>  include/uapi/drm/drm.h              |  24 +++
>  12 files changed, 543 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_syncobj.c
>  create mode 100644 include/drm/drm_syncobj.h
>
> diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-
> internals.rst
> index babfb61..2b23d78 100644
> --- a/Documentation/gpu/drm-internals.rst
> +++ b/Documentation/gpu/drm-internals.rst
> @@ -98,6 +98,9 @@ DRIVER_ATOMIC
>      implement appropriate obj->atomic_get_property() vfuncs for any
>      modeset objects with driver specific properties.
>
> +DRIVER_SYNCOBJ
> +    Driver support drm sync objects.
> +
>  Major, Minor and Patchlevel
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
> index 96b9c34..9412798 100644
> --- a/Documentation/gpu/drm-mm.rst
> +++ b/Documentation/gpu/drm-mm.rst
> @@ -484,3 +484,15 @@ DRM Cache Handling
>
>  .. kernel-doc:: drivers/gpu/drm/drm_cache.c
>     :export:
> +
> +DRM Sync Objects
> +===========================
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_syncobj.c
> +   :doc: Overview
> +
> +.. kernel-doc:: include/drm/drm_syncobj.h
> +   :export:
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_syncobj.c
> +   :export:
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 59f0f9b..6f42188 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -16,7 +16,7 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
>                 drm_framebuffer.o drm_connector.o drm_blend.o \
>                 drm_encoder.o drm_mode_object.o drm_property.o \
>                 drm_plane.o drm_color_mgmt.o drm_print.o \
> -               drm_dumb_buffers.o drm_mode_config.o
> +               drm_dumb_buffers.o drm_mode_config.o drm_syncobj.o
>
>  drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
>  drm-$(CONFIG_DRM_VM) += drm_vm.o
> diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
> index 3783b65..a20d6a9 100644
> --- a/drivers/gpu/drm/drm_file.c
> +++ b/drivers/gpu/drm/drm_file.c
> @@ -229,6 +229,9 @@ static int drm_open_helper(struct file *filp, struct
> drm_minor *minor)
>         if (drm_core_check_feature(dev, DRIVER_GEM))
>                 drm_gem_open(dev, priv);
>
> +       if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> +               drm_syncobj_open(priv);
> +
>         if (drm_core_check_feature(dev, DRIVER_PRIME))
>                 drm_prime_init_file_private(&priv->prime);
>
> @@ -276,6 +279,8 @@ static int drm_open_helper(struct file *filp, struct
> drm_minor *minor)
>  out_prime_destroy:
>         if (drm_core_check_feature(dev, DRIVER_PRIME))
>                 drm_prime_destroy_file_private(&priv->prime);
> +       if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> +               drm_syncobj_release(priv);
>         if (drm_core_check_feature(dev, DRIVER_GEM))
>                 drm_gem_release(dev, priv);
>         put_pid(priv->pid);
> @@ -398,6 +403,9 @@ int drm_release(struct inode *inode, struct file *filp)
>                 drm_property_destroy_user_blobs(dev, file_priv);
>         }
>
> +       if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> +               drm_syncobj_release(file_priv);
> +
>         if (drm_core_check_feature(dev, DRIVER_GEM))
>                 drm_gem_release(dev, file_priv);
>
> diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_
> internal.h
> index 3d8e8f8..3fdef2c 100644
> --- a/drivers/gpu/drm/drm_internal.h
> +++ b/drivers/gpu/drm/drm_internal.h
> @@ -142,4 +142,17 @@ static inline int drm_debugfs_crtc_crc_add(struct
> drm_crtc *crtc)
>  {
>         return 0;
>  }
> +
>  #endif
> +
> +/* drm_syncobj.c */
> +void drm_syncobj_open(struct drm_file *file_private);
> +void drm_syncobj_release(struct drm_file *file_private);
> +int drm_syncobj_create_ioctl(struct drm_device *dev, void *data,
> +                            struct drm_file *file_private);
> +int drm_syncobj_destroy_ioctl(struct drm_device *dev, void *data,
> +                             struct drm_file *file_private);
> +int drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data,
> +                                  struct drm_file *file_private);
> +int drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data,
> +                                  struct drm_file *file_private);
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index 865e3ee..f1e5681 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -241,6 +241,9 @@ static int drm_getcap(struct drm_device *dev, void
> *data, struct drm_file *file_
>                 req->value |= dev->driver->prime_fd_to_handle ?
> DRM_PRIME_CAP_IMPORT : 0;
>                 req->value |= dev->driver->prime_handle_to_fd ?
> DRM_PRIME_CAP_EXPORT : 0;
>                 return 0;
> +       case DRM_CAP_SYNCOBJ:
> +               req->value = drm_core_check_feature(dev, DRIVER_SYNCOBJ);
> +               return 0;
>         }
>
>         /* Other caps only work with KMS drivers */
> @@ -645,6 +648,15 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
>         DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl,
> DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>         DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB,
> drm_mode_createblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>         DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB,
> drm_mode_destroyblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +
> +       DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_CREATE, drm_syncobj_create_ioctl,
> +                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_DESTROY,
> drm_syncobj_destroy_ioctl,
> +                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD,
> drm_syncobj_handle_to_fd_ioctl,
> +                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
> +       DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE,
> drm_syncobj_fd_to_handle_ioctl,
> +                     DRM_UNLOCKED|DRM_RENDER_ALLOW),
>  };
>
>  #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
> new file mode 100644
> index 0000000..b611480
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_syncobj.c
> @@ -0,0 +1,377 @@
> +/*
> + * Copyright 2017 Red Hat
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> "Software"),
> + * to deal in the Software without restriction, including without
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> next
> + * paragraph) shall be included in all copies or substantial portions of
> the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *
> + */
> +
> +/**
> + * DOC: Overview
> + *
> + * DRM synchronisation objects (syncobj) are a persistent objects,
> + * that contain an optional fence. The fence can be updated with a new
> + * fence, or be NULL.
> + *
> + * syncobj's can be export to fd's and back, these fd's are opaque and
> + * have no other use case, except passing the syncobj between processes.
> + *
> + * Their primary use-case is to implement Vulkan fences and semaphores.
> + *
> + * syncobj have a kref reference count, but also have an optional file.
> + * The file is only created once the syncobj is exported.
> + * The file takes a reference on the kref.
> + */
> +
> +#include <drm/drmP.h>
> +#include <linux/file.h>
> +#include <linux/fs.h>
> +#include <linux/anon_inodes.h>
> +
> +#include "drm_internal.h"
> +#include <drm/drm_syncobj.h>
> +
> +static struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private,
> +                                          u32 handle)
> +{
> +       struct drm_syncobj *syncobj;
> +
> +       spin_lock(&file_private->syncobj_table_lock);
> +
> +       /* Check if we currently have a reference on the object */
> +       syncobj = idr_find(&file_private->syncobj_idr, handle);
> +       if (syncobj)
> +               drm_syncobj_get(syncobj);
> +
> +       spin_unlock(&file_private->syncobj_table_lock);
> +
> +       return syncobj;
> +}
> +
> +/**
> + * drm_syncobj_replace_fence - lookup and replace fence in a sync object.
> + * @file_private - drm file private pointer.
> + * @handle - syncobj handle to lookup
> + * @fence - fence to install in sync file.
> + * Returns:
> + * 0 on success, or -EINVAL when the handle doesn't point at a valid sem
> file.
> + *
> + * This looks up a sync object and replaces the fence on it, freeing
> + * the old one.
> + */
> +int drm_syncobj_replace_fence(struct drm_file *file_private,
> +                             u32 handle,
> +                             struct dma_fence *fence)
> +{
> +       struct drm_syncobj *syncobj = drm_syncobj_find(file_private,
> handle);
> +       struct dma_fence *old_fence = NULL;
> +
> +       if (!syncobj)
> +               return -EINVAL;
> +
> +       if (fence)
> +               dma_fence_get(fence);
> +       old_fence = xchg(&syncobj->fence, fence);
> +
> +       dma_fence_put(old_fence);
> +       drm_syncobj_put(syncobj);
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(drm_syncobj_replace_fence);
> +
> +int drm_syncobj_fence_get(struct drm_file *file_private,
> +                         u32 handle,
> +                         struct dma_fence **fence)
> +{
> +       struct drm_syncobj *syncobj = drm_syncobj_find(file_private,
> handle);
> +       int ret = 0;
> +
> +       if (!syncobj)
> +               return -ENOENT;
> +
> +       *fence = dma_fence_get(syncobj->fence);
> +       if (!*fence) {
> +               ret = -EINVAL;
> +       }
> +       drm_syncobj_put(syncobj);
> +       return ret;
> +}
> +EXPORT_SYMBOL(drm_syncobj_fence_get);
> +
> +void drm_syncobj_free(struct kref *kref)
> +{
> +       struct drm_syncobj *syncobj = container_of(kref,
> +                                                  struct drm_syncobj,
> +                                                  refcount);
> +       dma_fence_put(syncobj->fence);
> +       kfree(syncobj);
> +}
> +
> +static int drm_syncobj_create(struct drm_file *file_private,
> +                             u32 *handle)
> +{
> +       int ret;
> +       struct drm_syncobj *syncobj;
> +
> +       syncobj = kzalloc(sizeof(struct drm_syncobj), GFP_KERNEL);
> +       if (!syncobj)
> +               return -ENOMEM;
> +
> +       kref_init(&syncobj->refcount);
> +
> +       idr_preload(GFP_KERNEL);
> +       spin_lock(&file_private->syncobj_table_lock);
> +       ret = idr_alloc(&file_private->syncobj_idr, syncobj, 1, 0,
> GFP_NOWAIT);
> +       spin_unlock(&file_private->syncobj_table_lock);
> +
> +       idr_preload_end();
> +
> +       if (ret < 0) {
> +               drm_syncobj_put(syncobj);
> +               return ret;
> +       }
> +
> +       *handle = ret;
> +       return 0;
> +}
> +
> +static int drm_syncobj_destroy(struct drm_file *file_private,
> +                              u32 handle)
> +{
> +       struct drm_syncobj *syncobj;
> +
> +       spin_lock(&file_private->syncobj_table_lock);
> +       syncobj = idr_remove(&file_private->syncobj_idr, handle);
> +       spin_unlock(&file_private->syncobj_table_lock);
> +
> +       if (!syncobj)
> +               return -EINVAL;
> +
> +       drm_syncobj_put(syncobj);
> +       return 0;
> +}
> +
> +static int drm_syncobj_file_release(struct inode *inode, struct file
> *file)
> +{
> +       struct drm_syncobj *syncobj = file->private_data;
> +
> +       drm_syncobj_put(syncobj);
> +       return 0;
> +}
> +
> +static const struct file_operations drm_syncobj_file_fops = {
> +       .release = drm_syncobj_file_release,
> +};
> +
> +static int drm_syncobj_alloc_file(struct drm_syncobj *syncobj)
> +{
> +       struct file *file = anon_inode_getfile("syncobj_file",
> +                                              &drm_syncobj_file_fops,
> +                                              syncobj, 0);
> +       if (IS_ERR(file))
> +               return PTR_ERR(file);
> +
> +       drm_syncobj_get(syncobj);
> +       if (cmpxchg(&syncobj->file, NULL, file)) {
> +               /* lost the race */
> +               fput(file);
> +       }
> +
> +       return 0;
> +}
> +
> +static int drm_syncobj_handle_to_fd(struct drm_file *file_private,
> +                                   u32 handle, int *p_fd)
> +{
> +       struct drm_syncobj *syncobj = drm_syncobj_find(file_private,
> handle);
> +       int ret;
> +       int fd;
> +
> +       if (!syncobj)
> +               return -EINVAL;
> +
> +       fd = get_unused_fd_flags(O_CLOEXEC);
> +       if (fd < 0) {
> +               drm_syncobj_put(syncobj);
> +               return fd;
> +       }
> +
> +       if (!syncobj->file) {
> +               ret = drm_syncobj_alloc_file(syncobj);
> +               if (ret)
> +                       goto out_put_fd;
> +       }
> +       fd_install(fd, syncobj->file);
> +       drm_syncobj_put(syncobj);
> +       *p_fd = fd;
> +       return 0;
> +out_put_fd:
> +       put_unused_fd(fd);
> +       drm_syncobj_put(syncobj);
> +       return ret;
> +}
> +
> +static struct drm_syncobj *drm_syncobj_fdget(int fd)
> +{
> +       struct file *file = fget(fd);
> +
> +       if (!file)
> +               return NULL;
> +       if (file->f_op != &drm_syncobj_file_fops)
> +               goto err;
> +
> +       return file->private_data;
> +err:
> +       fput(file);
> +       return NULL;
> +};
> +
> +static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
> +                                   int fd, u32 *handle)
> +{
> +       struct drm_syncobj *syncobj = drm_syncobj_fdget(fd);
> +       int ret;
> +
> +       if (!syncobj)
> +               return -EINVAL;
> +
> +       /* take a reference to put in the idr */
> +       drm_syncobj_get(syncobj);
> +
> +       idr_preload(GFP_KERNEL);
> +       spin_lock(&file_private->syncobj_table_lock);
> +       ret = idr_alloc(&file_private->syncobj_idr, syncobj, 1, 0,
> GFP_NOWAIT);
> +       spin_unlock(&file_private->syncobj_table_lock);
> +       idr_preload_end();
> +
> +       if (ret < 0) {
> +               fput(syncobj->file);
> +               return ret;
> +       }
> +       *handle = ret;
> +       return 0;
> +}
> +
> +/**
> + * drm_syncobj_open - initalizes syncobj file-private structures at
> devnode open time
> + * @dev: drm_device which is being opened by userspace
> + * @file_private: drm file-private structure to set up
> + *
> + * Called at device open time, sets up the structure for handling
> refcounting
> + * of sync objects.
> + */
> +void
> +drm_syncobj_open(struct drm_file *file_private)
> +{
> +       idr_init(&file_private->syncobj_idr);
> +       spin_lock_init(&file_private->syncobj_table_lock);
> +}
> +
> +static int
> +drm_syncobj_release_handle(int id, void *ptr, void *data)
> +{
> +       struct drm_syncobj *syncobj = ptr;
> +
> +       drm_syncobj_put(syncobj);
> +       return 0;
> +}
> +
> +/**
> + * drm_syncobj_release - release file-private sync object resources
> + * @dev: drm_device which is being closed by userspace
> + * @file_private: drm file-private structure to clean up
> + *
> + * Called at close time when the filp is going away.
> + *
> + * Releases any remaining references on objects by this filp.
> + */
> +void
> +drm_syncobj_release(struct drm_file *file_private)
> +{
> +       idr_for_each(&file_private->syncobj_idr,
> +                    &drm_syncobj_release_handle, file_private);
> +       idr_destroy(&file_private->syncobj_idr);
> +}
> +
> +int
> +drm_syncobj_create_ioctl(struct drm_device *dev, void *data,
> +                        struct drm_file *file_private)
> +{
> +       struct drm_syncobj_create *args = data;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> +               return -ENODEV;
> +
> +       /* no valid flags yet */
> +       if (args->flags)
> +               return -EINVAL;
> +
> +       return drm_syncobj_create(file_private,
> +                                 &args->handle);
> +}
> +
> +int
> +drm_syncobj_destroy_ioctl(struct drm_device *dev, void *data,
> +                         struct drm_file *file_private)
> +{
> +       struct drm_syncobj_destroy *args = data;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> +               return -ENODEV;
> +
> +       /* make sure padding is empty */
> +       if (args->pad)
> +               return -EINVAL;
> +       return drm_syncobj_destroy(file_private, args->handle);
> +}
> +
> +int
> +drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data,
> +                                  struct drm_file *file_private)
> +{
> +       struct drm_syncobj_handle *args = data;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> +               return -ENODEV;
> +
> +       if (args->pad || args->flags)
> +               return -EINVAL;
> +
> +       return drm_syncobj_handle_to_fd(file_private, args->handle,
> +                                       &args->fd);
> +}
> +
> +int
> +drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data,
> +                                  struct drm_file *file_private)
> +{
> +       struct drm_syncobj_handle *args = data;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> +               return -ENODEV;
> +
> +       if (args->pad || args->flags)
> +               return -EINVAL;
> +
> +       return drm_syncobj_fd_to_handle(file_private, args->fd,
> +                                       &args->handle);
> +}
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index e1daa4f..4fad9f2 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -319,7 +319,6 @@ struct pci_controller;
>
>  #define DRM_IF_VERSION(maj, min) (maj << 16 | min)
>
> -
>  /* Flags and return codes for get_vblank_timestamp() driver function. */
>  #define DRM_CALLED_FROM_VBLIRQ 1
>  #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0)
> diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
> index 53b9832..1c66c1c 100644
> --- a/include/drm/drm_drv.h
> +++ b/include/drm/drm_drv.h
> @@ -53,6 +53,7 @@ struct drm_mode_create_dumb;
>  #define DRIVER_RENDER                  0x8000
>  #define DRIVER_ATOMIC                  0x10000
>  #define DRIVER_KMS_LEGACY_CONTEXT      0x20000
> +#define DRIVER_SYNCOBJ                  0x40000
>
>  /**
>   * struct drm_driver - DRM driver structure
> diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
> index 5dd27ae..cea7354 100644
> --- a/include/drm/drm_file.h
> +++ b/include/drm/drm_file.h
> @@ -231,6 +231,11 @@ struct drm_file {
>         /** @table_lock: Protects @object_idr. */
>         spinlock_t table_lock;
>
> +       /** @syncobj_idr: Mapping of sync object handles to object
> pointers. */
> +       struct idr syncobj_idr;
> +       /** @syncobj_table_lock: Protects @syncobj_idr. */
> +       spinlock_t syncobj_table_lock;
> +
>         /** @filp: Pointer to the core file structure. */
>         struct file *filp;
>
> diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h
> new file mode 100644
> index 0000000..372c398
> --- /dev/null
> +++ b/include/drm/drm_syncobj.h
> @@ -0,0 +1,87 @@
> +/*
> + * Copyright © 2017 Red Hat
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> "Software"),
> + * to deal in the Software without restriction, including without
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> next
> + * paragraph) shall be included in all copies or substantial portions of
> the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *
> + */
> +#ifndef __DRM_SYNCOBJ_H__
> +#define __DRM_SYNCOBJ_H__
> +
> +#include "linux/dma-fence.h"
> +
> +/**
> + * struct drm_syncobj - sync object.
> + *
> + * This structure defines a generic sync object which wraps a dma fence.
> + */
> +struct drm_syncobj {
> +       /**
> +        * @refcount:
> +        *
> +        * Reference count of this object.
> +        */
> +       struct kref refcount;
> +       /**
> +        * @fence:
> +        * NULL or a pointer to the fence bound to this object.
> +        */
> +       struct dma_fence *fence;
> +       /**
> +        * @file:
> +        * a file backing for this syncobj.
> +        */
> +       struct file *file;
> +};
> +
> +void drm_syncobj_free(struct kref *kref);
> +
> +/**
> + * drm_syncobj_get - acquire a syncobj reference
> + * @obj: sync object
> + *
> + * This acquires additional reference to @obj. It is illegal to call this
> + * without already holding a reference. No locks required.
> + */
> +static inline void
> +drm_syncobj_get(struct drm_syncobj *obj)
> +{
> +       kref_get(&obj->refcount);
> +}
> +
> +/**
> + * drm_syncobj_put - release a reference to a sync object.
> + * @obj: sync object.
> + */
> +static inline void
> +drm_syncobj_put(struct drm_syncobj *obj)
> +{
> +       kref_put(&obj->refcount, drm_syncobj_free);
> +}
> +
> +int drm_syncobj_fence_get(struct drm_file *file_private,
> +                         u32 handle,
> +                         struct dma_fence **fence);
> +int drm_syncobj_replace_fence(struct drm_file *file_private,
> +                             u32 handle,
> +                             struct dma_fence *fence);
> +
> +#endif
> diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
> index 42d9f64..96c5c78 100644
> --- a/include/uapi/drm/drm.h
> +++ b/include/uapi/drm/drm.h
> @@ -648,6 +648,7 @@ struct drm_gem_open {
>  #define DRM_CAP_ADDFB2_MODIFIERS       0x10
>  #define DRM_CAP_PAGE_FLIP_TARGET       0x11
>  #define DRM_CAP_CRTC_IN_VBLANK_EVENT   0x12
> +#define DRM_CAP_SYNCOBJ                0x13
>
>  /** DRM_IOCTL_GET_CAP ioctl argument type */
>  struct drm_get_cap {
> @@ -697,6 +698,24 @@ struct drm_prime_handle {
>         __s32 fd;
>  };
>
> +struct drm_syncobj_create {
> +       __u32 handle;
> +       __u32 flags;
> +};
> +
> +struct drm_syncobj_destroy {
> +       __u32 handle;
> +       __u32 pad;
> +};
> +
> +struct drm_syncobj_handle {
> +       __u32 handle;
> +       __u32 flags;
> +
> +       __s32 fd;
> +       __u32 pad;
> +};
> +
>  #if defined(__cplusplus)
>  }
>  #endif
> @@ -815,6 +834,11 @@ extern "C" {
>  #define DRM_IOCTL_MODE_CREATEPROPBLOB  DRM_IOWR(0xBD, struct
> drm_mode_create_blob)
>  #define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct
> drm_mode_destroy_blob)
>
> +#define DRM_IOCTL_SYNCOBJ_CREATE       DRM_IOWR(0xBF, struct
> drm_syncobj_create)
> +#define DRM_IOCTL_SYNCOBJ_DESTROY      DRM_IOWR(0xC0, struct
> drm_syncobj_destroy)
> +#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct
> drm_syncobj_handle)
> +#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct
> drm_syncobj_handle)
> +
>  /**
>   * Device specific ioctls should only be in their respective headers
>   * The device specific ioctl range is from 0x40 to 0x9f.
> --
> 2.9.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20170524/001b6205/attachment-0001.html>


More information about the dri-devel mailing list