summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-08-04 12:25:39 +1000
committerDave Airlie <airlied@redhat.com>2017-08-04 12:55:10 +1000
commit77645c44e3fc32028b3bef3b75889c1524b8df3a (patch)
treeefc97060b1b5f3574f6b3f39cdf7513314d40d18
parente4146d683fb9dbe05a6779ad4190b725019e7475 (diff)
drm/syncobj: allow wait on unsignalled semanticsdrm-syncobj-wait-null
not even close to working
-rw-r--r--drivers/gpu/drm/drm_syncobj.c62
-rw-r--r--include/drm/drm_syncobj.h2
-rw-r--r--include/uapi/drm/drm.h2
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 */