summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdrm/xf86drm.c15
-rw-r--r--libdrm/xf86drm.h1
-rw-r--r--linux-core/drmP.h14
-rw-r--r--linux-core/drm_bo.c33
-rw-r--r--linux-core/drm_fence.c96
-rw-r--r--shared-core/drm.h3
6 files changed, 105 insertions, 57 deletions
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index 068d0fb9..6d087427 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -2259,6 +2259,21 @@ int drmFenceCreate(int fd, int shareable, int class,unsigned type,
fence->signaled = 0;
return 0;
}
+
+int drmFenceBuffers(int fd, int shareable, drmFence *fence)
+{
+ drm_fence_arg_t arg;
+
+ arg.flags = (shareable) ? DRM_FENCE_FLAG_SHAREABLE : 0;
+ arg.op = drm_fence_buffers;
+ if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+ return -errno;
+ fence->handle = arg.handle;
+ fence->class = arg.class;
+ fence->type = arg.type;
+ fence->signaled = 0;
+ return 0;
+}
int drmFenceDestroy(int fd, const drmFence *fence)
{
diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h
index f257deda..be1eeeff 100644
--- a/libdrm/xf86drm.h
+++ b/libdrm/xf86drm.h
@@ -626,6 +626,7 @@ extern int drmFenceSignaled(int fd, drmFence *fence);
extern int drmFenceWait(int fd, drmFence *fence, unsigned flush_type,
int lazy, int ignore_signals);
extern int drmFenceEmit(int fd, drmFence *fence, unsigned emit_type);
+extern int drmFenceBuffers(int fd, int shareable, drmFence *fence);
/* TTMS */
extern int drmTTMCreate(int fd, drmTTM *ttm, unsigned long size,
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 23766373..7de7422b 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -1379,10 +1379,16 @@ extern void drm_fence_usage_deref_locked(drm_device_t * dev,
drm_fence_object_t * fence);
extern void drm_fence_usage_deref_unlocked(drm_device_t * dev,
drm_fence_object_t * fence);
-extern int drm_fence_object_init(drm_device_t * dev, uint32_t type, int emit,
- drm_fence_object_t * fence);
extern int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence,
int lazy, int ignore_signals, uint32_t mask);
+extern int drm_fence_object_create(drm_device_t *dev, uint32_t type,
+ int emit, drm_fence_object_t **c_fence);
+extern int drm_fence_add_user_object(drm_file_t *priv,
+ drm_fence_object_t *fence,
+ int shareable);
+
+
+
extern int drm_fence_ioctl(DRM_IOCTL_ARGS);
@@ -1394,6 +1400,10 @@ extern int drm_fence_ioctl(DRM_IOCTL_ARGS);
extern int drm_bo_ioctl(DRM_IOCTL_ARGS);
extern int drm_mm_init_ioctl(DRM_IOCTL_ARGS);
extern int drm_bo_clean_mm(drm_device_t *dev);
+extern int drm_fence_buffer_objects(drm_file_t * priv,
+ struct list_head *list,
+ drm_fence_object_t *fence,
+ drm_fence_object_t **used_fence);
/* Inline replacements for DRM_IOREMAP macros */
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 1f0bbba5..68af5c31 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -199,8 +199,15 @@ void drm_bo_usage_deref_unlocked(drm_device_t * dev, drm_buffer_object_t * bo)
}
}
+/*
+ * Note. The caller has to register (if applicable)
+ * and deregister fence object usage.
+ */
+
int drm_fence_buffer_objects(drm_file_t * priv,
- struct list_head *list, drm_fence_object_t * fence)
+ struct list_head *list,
+ drm_fence_object_t *fence,
+ drm_fence_object_t **used_fence)
{
drm_device_t *dev = priv->head->dev;
drm_buffer_manager_t *bm = &dev->bm;
@@ -230,19 +237,9 @@ int drm_fence_buffer_objects(drm_file_t * priv,
goto out;
}
} else {
- fence = kmem_cache_alloc(drm_cache.fence_object, GFP_KERNEL);
-
- if (!fence) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = drm_fence_object_init(dev, fence_flags, 1, fence);
-
- if (ret) {
- kmem_cache_free(drm_cache.fence_object, fence);
- goto out;
- }
+ ret = drm_fence_object_create(dev, fence_flags, 1, &fence);
+ if (ret)
+ goto out;
}
/*
@@ -285,14 +282,14 @@ int drm_fence_buffer_objects(drm_file_t * priv,
drm_bo_usage_deref_locked(dev, entry);
l = f_list.next;
}
- if (!count)
- drm_fence_usage_deref_locked(dev, fence);
- else if (count > 1)
- atomic_add(count - 1, &fence->usage);
+ atomic_add(count, &fence->usage);
out:
mutex_unlock(&dev->struct_mutex);
+ *used_fence = fence;
return ret;
}
+EXPORT_SYMBOL(drm_fence_buffer_objects);
+
/*
* Call bo->mutex locked.
diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c
index 1deeaaa5..fd43d8bc 100644
--- a/linux-core/drm_fence.c
+++ b/linux-core/drm_fence.c
@@ -417,14 +417,28 @@ int drm_fence_object_init(drm_device_t * dev, uint32_t type, int emit,
EXPORT_SYMBOL(drm_fence_object_init);
-static int drm_fence_object_create(drm_file_t * priv, uint32_t type,
- int emit, int shareable,
- uint32_t * user_handle,
- drm_fence_object_t ** c_fence)
+int drm_fence_add_user_object(drm_file_t *priv, drm_fence_object_t *fence,
+ int shareable)
{
drm_device_t *dev = priv->head->dev;
int ret;
+
+ mutex_lock(&dev->struct_mutex);
+ ret = drm_add_user_object(priv, &fence->base, shareable);
+ mutex_unlock(&dev->struct_mutex);
+ if (ret)
+ return ret;
+ fence->base.type = drm_fence_type;
+ fence->base.remove = &drm_fence_object_destroy;
+ return 0;
+}
+EXPORT_SYMBOL(drm_fence_add_user_object);
+
+int drm_fence_object_create(drm_device_t *dev, uint32_t type,
+ int emit, drm_fence_object_t **c_fence)
+{
drm_fence_object_t *fence;
+ int ret;
fence = kmem_cache_alloc(drm_cache.fence_object, GFP_KERNEL);
if (!fence)
@@ -434,23 +448,11 @@ static int drm_fence_object_create(drm_file_t * priv, uint32_t type,
drm_fence_usage_deref_unlocked(dev, fence);
return ret;
}
-
- mutex_lock(&dev->struct_mutex);
- ret = drm_add_user_object(priv, &fence->base, shareable);
- mutex_unlock(&dev->struct_mutex);
- if (ret) {
- drm_fence_usage_deref_unlocked(dev, fence);
- *c_fence = NULL;
- *user_handle = 0;
- return ret;
- }
- fence->base.type = drm_fence_type;
- fence->base.remove = &drm_fence_object_destroy;
- *user_handle = fence->base.hash.key;
- *c_fence = fence;
-
+ *c_fence = fence;
return 0;
}
+EXPORT_SYMBOL(drm_fence_object_create);
+
void drm_fence_manager_init(drm_device_t * dev)
{
@@ -511,24 +513,29 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
switch (arg.op) {
- case drm_fence_create:{
- int emit = arg.flags & DRM_FENCE_FLAG_EMIT;
- if (emit)
- LOCK_TEST_WITH_RETURN(dev, filp);
- ret =
- drm_fence_object_create(priv, arg.type,
- emit,
- arg.
- flags &
- DRM_FENCE_FLAG_SHAREABLE,
- &arg.handle, &fence);
- if (ret)
- return ret;
- mutex_lock(&dev->struct_mutex);
- atomic_inc(&fence->usage);
- mutex_unlock(&dev->struct_mutex);
- break;
+ case drm_fence_create:
+ if (arg.flags & DRM_FENCE_FLAG_EMIT)
+ LOCK_TEST_WITH_RETURN(dev, filp);
+ ret = drm_fence_object_create(dev, arg.type,
+ arg.flags & DRM_FENCE_FLAG_EMIT,
+ &fence);
+ if (ret)
+ return ret;
+ ret = drm_fence_add_user_object(priv, fence,
+ arg.flags &
+ DRM_FENCE_FLAG_SHAREABLE);
+ if (ret) {
+ drm_fence_usage_deref_unlocked(dev, fence);
+ return ret;
}
+
+ /*
+ * usage > 0. No need to lock dev->struct_mutex;
+ */
+
+ atomic_inc(&fence->usage);
+ arg.handle = fence->base.hash.key;
+ break;
case drm_fence_destroy:
mutex_lock(&dev->struct_mutex);
uo = drm_lookup_user_object(priv, arg.handle);
@@ -577,6 +584,23 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
return -EINVAL;
ret = drm_fence_object_emit(dev, fence, arg.type);
break;
+ case drm_fence_buffers:
+ if (!dev->bm.initialized) {
+ DRM_ERROR("Buffer object manager is not initialized\n");
+ return -EINVAL;
+ }
+ LOCK_TEST_WITH_RETURN(dev, filp);
+ ret = drm_fence_buffer_objects(priv, NULL, NULL, &fence);
+ if (ret)
+ return ret;
+ ret = drm_fence_add_user_object(priv, fence,
+ arg.flags &
+ DRM_FENCE_FLAG_SHAREABLE);
+ if (ret)
+ return ret;
+ atomic_inc(&fence->usage);
+ arg.handle = fence->base.hash.key;
+ break;
default:
return -EINVAL;
}
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 1a43e0af..e39f888a 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -659,7 +659,8 @@ typedef struct drm_fence_arg {
drm_fence_signaled,
drm_fence_flush,
drm_fence_wait,
- drm_fence_emit
+ drm_fence_emit,
+ drm_fence_buffers
} op;
} drm_fence_arg_t;