diff options
author | Dave Airlie <airlied@redhat.com> | 2017-08-04 12:25:39 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-08-04 12:55:10 +1000 |
commit | 77645c44e3fc32028b3bef3b75889c1524b8df3a (patch) | |
tree | efc97060b1b5f3574f6b3f39cdf7513314d40d18 | |
parent | e4146d683fb9dbe05a6779ad4190b725019e7475 (diff) |
drm/syncobj: allow wait on unsignalled semanticsdrm-syncobj-wait-null
not even close to working
-rw-r--r-- | drivers/gpu/drm/drm_syncobj.c | 62 | ||||
-rw-r--r-- | include/drm/drm_syncobj.h | 2 | ||||
-rw-r--r-- | include/uapi/drm/drm.h | 2 |
3 files changed, 61 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index a8b7611810fb..ab3c5a3bccb0 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -55,6 +55,39 @@ #include "drm_internal.h" #include <drm/drm_syncobj.h> +static DEFINE_SPINLOCK(drm_syncobj_null_fence_lock); + +static const char *drm_syncobj_fence_get_driver_name(struct dma_fence *fence) +{ + return "syncobjnull"; +} + +static const char *drm_syncobj_fence_get_timeline_name(struct dma_fence *f) +{ + return "syncobjnull"; +} + +static const struct dma_fence_ops nullsyncobj_fence_ops = { + .get_driver_name = drm_syncobj_fence_get_driver_name, + .get_timeline_name = drm_syncobj_fence_get_timeline_name, + .enable_signaling = NULL, + .wait = dma_fence_default_wait, + .release = NULL, +}; + +static struct dma_fence *drm_syncobj_create_null_fence(void) +{ + struct dma_fence *fence; + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (fence == NULL) + return NULL; + + dma_fence_init(fence, &nullsyncobj_fence_ops, + &drm_syncobj_null_fence_lock, + 0, 0); + return fence; +} + /** * drm_syncobj_find - lookup and reference a sync object. * @file_private: drm file private pointer @@ -98,6 +131,10 @@ void drm_syncobj_replace_fence(struct drm_file *file_private, dma_fence_get(fence); old_fence = xchg(&syncobj->fence, fence); + if (syncobj->null_fence_attached) { + dma_fence_signal(old_fence); + syncobj->null_fence_attached = false; + } dma_fence_put(old_fence); } EXPORT_SYMBOL(drm_syncobj_replace_fence); @@ -138,7 +175,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, bool allow_null_wait) { int ret; struct drm_syncobj *syncobj; @@ -149,6 +186,15 @@ static int drm_syncobj_create(struct drm_file *file_private, kref_init(&syncobj->refcount); + if (allow_null_wait) { + struct dma_fence *null_fence = drm_syncobj_create_null_fence(); + + syncobj->null_fence_attached = true; + drm_syncobj_replace_fence(file_private, + syncobj, + null_fence); + } + idr_preload(GFP_KERNEL); spin_lock(&file_private->syncobj_table_lock); ret = idr_alloc(&file_private->syncobj_idr, syncobj, 1, 0, GFP_NOWAIT); @@ -385,12 +431,13 @@ drm_syncobj_create_ioctl(struct drm_device *dev, void *data, if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) return -ENODEV; - /* no valid flags yet */ - if (args->flags) + if (args->flags != 0 && + args->flags != DRM_SYNCOBJ_CREATE_FLAGS_ALLOW_NULL_WAIT) return -EINVAL; return drm_syncobj_create(file_private, - &args->handle); + &args->handle, + !!(args->flags & DRM_SYNCOBJ_CREATE_FLAGS_ALLOW_NULL_WAIT)); } int @@ -539,7 +586,8 @@ drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) return -ENODEV; - if (args->flags != 0 && args->flags != DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL) + if (args->flags != 0 && + !(args->flags & (DRM_SYNCOBJ_WAIT_NULL_FENCE_SIGNAL|DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL))) return -EINVAL; if (args->count_handles == 0) @@ -568,6 +616,10 @@ drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, for (i = 0; i < args->count_handles; i++) { ret = drm_syncobj_fence_get(file_private, handles[i], &fences[i]); + if (ret == -EINVAL && (args->flags & DRM_SYNCOBJ_WAIT_NULL_FENCE_SIGNAL)) { + + } + /* do magic */ if (ret) goto err_free_fence_array; } diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h index 2c3610a4a074..6f61ffbe10c7 100644 --- a/include/drm/drm_syncobj.h +++ b/include/drm/drm_syncobj.h @@ -50,6 +50,8 @@ struct drm_syncobj { * a file backing for this syncobj. */ struct file *file; + + bool null_fence_attached; }; void drm_syncobj_free(struct kref *kref); diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 0757c1a41821..f9fc42dc9f8c 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -698,6 +698,7 @@ struct drm_prime_handle { __s32 fd; }; +#define DRM_SYNCOBJ_CREATE_FLAGS_ALLOW_NULL_WAIT (1 << 0) struct drm_syncobj_create { __u32 handle; __u32 flags; @@ -719,6 +720,7 @@ struct drm_syncobj_handle { }; #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) +#define DRM_SYNCOBJ_WAIT_NULL_FENCE_SIGNAL (1 << 1) struct drm_syncobj_wait { __u64 handles; /* absolute timeout */ |