From 6e637fe881dd2342bf690e6d7f13e8ba7a09c3a1 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 25 Aug 2017 10:52:25 -0700 Subject: [PATCH] drm/syncobj: Add a CREATE_SIGNALED flag This requests that the driver create the sync object such that it already has a signaled dma_fence attached. Because we don't need anything in particular (just something signaled), we use a dummy null fence. This is useful for Vulkan which has a similar flag that can be passed to vkCreateFence. Signed-off-by: Jason Ekstrand Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_syncobj.c | 57 +++++++++++++++++++++++++++++++++-- include/uapi/drm/drm.h | 1 + 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index bade497b3f1de..12db8c9564cd0 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -154,6 +154,49 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, } EXPORT_SYMBOL(drm_syncobj_replace_fence); +struct drm_syncobj_null_fence { + struct dma_fence base; + spinlock_t lock; +}; + +static const char *drm_syncobj_null_fence_get_name(struct dma_fence *fence) +{ + return "syncobjnull"; +} + +static bool drm_syncobj_null_fence_enable_signaling(struct dma_fence *fence) +{ + dma_fence_enable_sw_signaling(fence); + return !dma_fence_is_signaled(fence); +} + +static const struct dma_fence_ops drm_syncobj_null_fence_ops = { + .get_driver_name = drm_syncobj_null_fence_get_name, + .get_timeline_name = drm_syncobj_null_fence_get_name, + .enable_signaling = drm_syncobj_null_fence_enable_signaling, + .wait = dma_fence_default_wait, + .release = NULL, +}; + +static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj) +{ + struct drm_syncobj_null_fence *fence; + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (fence == NULL) + return -ENOMEM; + + spin_lock_init(&fence->lock); + dma_fence_init(&fence->base, &drm_syncobj_null_fence_ops, + &fence->lock, 0, 0); + dma_fence_signal(&fence->base); + + drm_syncobj_replace_fence(syncobj, &fence->base); + + dma_fence_put(&fence->base); + + return 0; +} + int drm_syncobj_find_fence(struct drm_file *file_private, u32 handle, struct dma_fence **fence) @@ -190,7 +233,7 @@ void drm_syncobj_free(struct kref *kref) EXPORT_SYMBOL(drm_syncobj_free); static int drm_syncobj_create(struct drm_file *file_private, - u32 *handle) + u32 *handle, uint32_t flags) { int ret; struct drm_syncobj *syncobj; @@ -203,6 +246,14 @@ static int drm_syncobj_create(struct drm_file *file_private, INIT_LIST_HEAD(&syncobj->cb_list); spin_lock_init(&syncobj->lock); + if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) { + ret = drm_syncobj_assign_null_handle(syncobj); + if (ret < 0) { + drm_syncobj_put(syncobj); + return ret; + } + } + idr_preload(GFP_KERNEL); spin_lock(&file_private->syncobj_table_lock); ret = idr_alloc(&file_private->syncobj_idr, syncobj, 1, 0, GFP_NOWAIT); @@ -438,11 +489,11 @@ drm_syncobj_create_ioctl(struct drm_device *dev, void *data, return -ENODEV; /* no valid flags yet */ - if (args->flags) + if (args->flags & ~DRM_SYNCOBJ_CREATE_SIGNALED) return -EINVAL; return drm_syncobj_create(file_private, - &args->handle); + &args->handle, args->flags); } int diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 0757c1a418212..ade7f68d32b53 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -700,6 +700,7 @@ struct drm_prime_handle { struct drm_syncobj_create { __u32 handle; +#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0) __u32 flags; }; -- 2.39.5