summaryrefslogtreecommitdiff
path: root/linux-core/drm_fence.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core/drm_fence.c')
-rw-r--r--linux-core/drm_fence.c587
1 files changed, 385 insertions, 202 deletions
diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c
index ce161dc3..2f16f7ef 100644
--- a/linux-core/drm_fence.c
+++ b/linux-core/drm_fence.c
@@ -34,17 +34,17 @@
* Typically called by the IRQ handler.
*/
-void drm_fence_handler(drm_device_t * dev, uint32_t class,
+void drm_fence_handler(struct drm_device * dev, uint32_t class,
uint32_t sequence, uint32_t type)
{
int wake = 0;
uint32_t diff;
uint32_t relevant;
- drm_fence_manager_t *fm = &dev->fm;
- drm_fence_class_manager_t *fc = &fm->class[class];
- drm_fence_driver_t *driver = dev->driver->fence_driver;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_class_manager *fc = &fm->class[class];
+ struct drm_fence_driver *driver = dev->driver->fence_driver;
struct list_head *head;
- drm_fence_object_t *fence, *next;
+ struct drm_fence_object *fence, *next;
int found = 0;
int is_exe = (type & DRM_FENCE_TYPE_EXE);
int ge_last_exe;
@@ -114,9 +114,9 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
EXPORT_SYMBOL(drm_fence_handler);
-static void drm_fence_unring(drm_device_t * dev, struct list_head *ring)
+static void drm_fence_unring(struct drm_device * dev, struct list_head *ring)
{
- drm_fence_manager_t *fm = &dev->fm;
+ struct drm_fence_manager *fm = &dev->fm;
unsigned long flags;
write_lock_irqsave(&fm->lock, flags);
@@ -124,54 +124,78 @@ static void drm_fence_unring(drm_device_t * dev, struct list_head *ring)
write_unlock_irqrestore(&fm->lock, flags);
}
-void drm_fence_usage_deref_locked(drm_device_t * dev,
- drm_fence_object_t * fence)
+void drm_fence_usage_deref_locked(struct drm_fence_object ** fence)
{
- drm_fence_manager_t *fm = &dev->fm;
-
- if (atomic_dec_and_test(&fence->usage)) {
- drm_fence_unring(dev, &fence->ring);
+ struct drm_fence_object *tmp_fence = *fence;
+ struct drm_device *dev = tmp_fence->dev;
+ struct drm_fence_manager *fm = &dev->fm;
+
+ DRM_ASSERT_LOCKED(&dev->struct_mutex);
+ *fence = NULL;
+ if (atomic_dec_and_test(&tmp_fence->usage)) {
+ drm_fence_unring(dev, &tmp_fence->ring);
DRM_DEBUG("Destroyed a fence object 0x%08lx\n",
- fence->base.hash.key);
+ tmp_fence->base.hash.key);
atomic_dec(&fm->count);
- drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE);
+ BUG_ON(!list_empty(&tmp_fence->base.list));
+ drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
}
}
-void drm_fence_usage_deref_unlocked(drm_device_t * dev,
- drm_fence_object_t * fence)
+void drm_fence_usage_deref_unlocked(struct drm_fence_object ** fence)
{
- drm_fence_manager_t *fm = &dev->fm;
+ struct drm_fence_object *tmp_fence = *fence;
+ struct drm_device *dev = tmp_fence->dev;
+ struct drm_fence_manager *fm = &dev->fm;
- if (atomic_dec_and_test(&fence->usage)) {
+ *fence = NULL;
+ if (atomic_dec_and_test(&tmp_fence->usage)) {
mutex_lock(&dev->struct_mutex);
- if (atomic_read(&fence->usage) == 0) {
- drm_fence_unring(dev, &fence->ring);
+ if (atomic_read(&tmp_fence->usage) == 0) {
+ drm_fence_unring(dev, &tmp_fence->ring);
atomic_dec(&fm->count);
- drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE);
+ BUG_ON(!list_empty(&tmp_fence->base.list));
+ drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
}
mutex_unlock(&dev->struct_mutex);
}
}
-static void drm_fence_object_destroy(drm_file_t * priv,
- drm_user_object_t * base)
+struct drm_fence_object
+*drm_fence_reference_locked(struct drm_fence_object *src)
{
- drm_device_t *dev = priv->head->dev;
- drm_fence_object_t *fence =
- drm_user_object_entry(base, drm_fence_object_t, base);
+ DRM_ASSERT_LOCKED(&src->dev->struct_mutex);
- drm_fence_usage_deref_locked(dev, fence);
+ atomic_inc(&src->usage);
+ return src;
}
-static int fence_signaled(drm_device_t * dev,
- drm_fence_object_t * fence,
- uint32_t mask, int poke_flush)
+void drm_fence_reference_unlocked(struct drm_fence_object **dst,
+ struct drm_fence_object *src)
+{
+ mutex_lock(&src->dev->struct_mutex);
+ *dst = src;
+ atomic_inc(&src->usage);
+ mutex_unlock(&src->dev->struct_mutex);
+}
+
+
+static void drm_fence_object_destroy(struct drm_file *priv, struct drm_user_object * base)
+{
+ struct drm_fence_object *fence =
+ drm_user_object_entry(base, struct drm_fence_object, base);
+
+ drm_fence_usage_deref_locked(&fence);
+}
+
+int drm_fence_object_signaled(struct drm_fence_object * fence,
+ uint32_t mask, int poke_flush)
{
unsigned long flags;
int signaled;
- drm_fence_manager_t *fm = &dev->fm;
- drm_fence_driver_t *driver = dev->driver->fence_driver;
+ struct drm_device *dev = fence->dev;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_driver *driver = dev->driver->fence_driver;
if (poke_flush)
driver->poke_flush(dev, fence->class);
@@ -183,8 +207,8 @@ static int fence_signaled(drm_device_t * dev,
return signaled;
}
-static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
- drm_fence_driver_t * driver, uint32_t sequence)
+static void drm_fence_flush_exe(struct drm_fence_class_manager * fc,
+ struct drm_fence_driver * driver, uint32_t sequence)
{
uint32_t diff;
@@ -200,19 +224,13 @@ static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
}
}
-int drm_fence_object_signaled(drm_fence_object_t * fence,
- uint32_t type)
-{
- return ((fence->signaled & type) == type);
-}
-
-int drm_fence_object_flush(drm_device_t * dev,
- drm_fence_object_t * fence,
+int drm_fence_object_flush(struct drm_fence_object * fence,
uint32_t type)
{
- drm_fence_manager_t *fm = &dev->fm;
- drm_fence_class_manager_t *fc = &fm->class[fence->class];
- drm_fence_driver_t *driver = dev->driver->fence_driver;
+ struct drm_device *dev = fence->dev;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_class_manager *fc = &fm->class[fence->class];
+ struct drm_fence_driver *driver = dev->driver->fence_driver;
unsigned long flags;
if (type & ~fence->type) {
@@ -244,14 +262,14 @@ int drm_fence_object_flush(drm_device_t * dev,
* wrapped around and reused.
*/
-void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
+void drm_fence_flush_old(struct drm_device * dev, uint32_t class, uint32_t sequence)
{
- drm_fence_manager_t *fm = &dev->fm;
- drm_fence_class_manager_t *fc = &fm->class[class];
- drm_fence_driver_t *driver = dev->driver->fence_driver;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_class_manager *fc = &fm->class[class];
+ struct drm_fence_driver *driver = dev->driver->fence_driver;
uint32_t old_sequence;
unsigned long flags;
- drm_fence_object_t *fence;
+ struct drm_fence_object *fence;
uint32_t diff;
write_lock_irqsave(&fm->lock, flags);
@@ -272,39 +290,38 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
mutex_unlock(&dev->struct_mutex);
return;
}
- fence = list_entry(fc->ring.next, drm_fence_object_t, ring);
- atomic_inc(&fence->usage);
+ fence = drm_fence_reference_locked(list_entry(fc->ring.next, struct drm_fence_object, ring));
mutex_unlock(&dev->struct_mutex);
diff = (old_sequence - fence->sequence) & driver->sequence_mask;
read_unlock_irqrestore(&fm->lock, flags);
if (diff < driver->wrap_diff) {
- drm_fence_object_flush(dev, fence, fence->type);
+ drm_fence_object_flush(fence, fence->type);
}
- drm_fence_usage_deref_unlocked(dev, fence);
+ drm_fence_usage_deref_unlocked(&fence);
}
EXPORT_SYMBOL(drm_fence_flush_old);
-static int drm_fence_lazy_wait(drm_device_t *dev,
- drm_fence_object_t *fence,
+static int drm_fence_lazy_wait(struct drm_fence_object *fence,
int ignore_signals,
uint32_t mask)
{
- drm_fence_manager_t *fm = &dev->fm;
- drm_fence_class_manager_t *fc = &fm->class[fence->class];
+ struct drm_device *dev = fence->dev;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_class_manager *fc = &fm->class[fence->class];
int signaled;
unsigned long _end = jiffies + 3*DRM_HZ;
int ret = 0;
do {
DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ,
- (signaled = fence_signaled(dev, fence, mask, 1)));
+ (signaled = drm_fence_object_signaled(fence, mask, 1)));
if (signaled)
return 0;
if (time_after_eq(jiffies, _end))
break;
} while (ret == -EINTR && ignore_signals);
- if (fence_signaled(dev, fence, mask, 0))
+ if (drm_fence_object_signaled(fence, mask, 0))
return 0;
if (time_after_eq(jiffies, _end))
ret = -EBUSY;
@@ -319,11 +336,11 @@ static int drm_fence_lazy_wait(drm_device_t *dev,
return 0;
}
-int drm_fence_object_wait(drm_device_t * dev,
- drm_fence_object_t * fence,
+int drm_fence_object_wait(struct drm_fence_object * fence,
int lazy, int ignore_signals, uint32_t mask)
{
- drm_fence_driver_t *driver = dev->driver->fence_driver;
+ struct drm_device *dev = fence->dev;
+ struct drm_fence_driver *driver = dev->driver->fence_driver;
int ret = 0;
unsigned long _end;
int signaled;
@@ -334,16 +351,16 @@ int drm_fence_object_wait(drm_device_t * dev,
return -EINVAL;
}
- if (fence_signaled(dev, fence, mask, 0))
+ if (drm_fence_object_signaled(fence, mask, 0))
return 0;
_end = jiffies + 3 * DRM_HZ;
- drm_fence_object_flush(dev, fence, mask);
+ drm_fence_object_flush(fence, mask);
if (lazy && driver->lazy_capable) {
- ret = drm_fence_lazy_wait(dev, fence, ignore_signals, mask);
+ ret = drm_fence_lazy_wait(fence, ignore_signals, mask);
if (ret)
return ret;
@@ -351,7 +368,7 @@ int drm_fence_object_wait(drm_device_t * dev,
if (driver->has_irq(dev, fence->class,
DRM_FENCE_TYPE_EXE)) {
- ret = drm_fence_lazy_wait(dev, fence, ignore_signals,
+ ret = drm_fence_lazy_wait(fence, ignore_signals,
DRM_FENCE_TYPE_EXE);
if (ret)
return ret;
@@ -359,13 +376,13 @@ int drm_fence_object_wait(drm_device_t * dev,
if (driver->has_irq(dev, fence->class,
mask & ~DRM_FENCE_TYPE_EXE)) {
- ret = drm_fence_lazy_wait(dev, fence, ignore_signals,
+ ret = drm_fence_lazy_wait(fence, ignore_signals,
mask);
if (ret)
return ret;
}
}
- if (drm_fence_object_signaled(fence, mask))
+ if (drm_fence_object_signaled(fence, mask, 0))
return 0;
/*
@@ -377,7 +394,7 @@ int drm_fence_object_wait(drm_device_t * dev,
#endif
do {
schedule();
- signaled = fence_signaled(dev, fence, mask, 1);
+ signaled = drm_fence_object_signaled(fence, mask, 1);
} while (!signaled && !time_after_eq(jiffies, _end));
if (!signaled)
@@ -386,12 +403,13 @@ int drm_fence_object_wait(drm_device_t * dev,
return 0;
}
-int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
+int drm_fence_object_emit(struct drm_fence_object * fence,
uint32_t fence_flags, uint32_t class, uint32_t type)
{
- drm_fence_manager_t *fm = &dev->fm;
- drm_fence_driver_t *driver = dev->driver->fence_driver;
- drm_fence_class_manager_t *fc = &fm->class[fence->class];
+ struct drm_device *dev = fence->dev;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_driver *driver = dev->driver->fence_driver;
+ struct drm_fence_class_manager *fc = &fm->class[fence->class];
unsigned long flags;
uint32_t sequence;
uint32_t native_type;
@@ -417,14 +435,14 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
return 0;
}
-static int drm_fence_object_init(drm_device_t * dev, uint32_t class,
+static int drm_fence_object_init(struct drm_device * dev, uint32_t class,
uint32_t type,
uint32_t fence_flags,
- drm_fence_object_t * fence)
+ struct drm_fence_object * fence)
{
int ret = 0;
unsigned long flags;
- drm_fence_manager_t *fm = &dev->fm;
+ struct drm_fence_manager *fm = &dev->fm;
mutex_lock(&dev->struct_mutex);
atomic_set(&fence->usage, 1);
@@ -432,52 +450,60 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t class,
write_lock_irqsave(&fm->lock, flags);
INIT_LIST_HEAD(&fence->ring);
+
+ /*
+ * Avoid hitting BUG() for kernel-only fence objects.
+ */
+
+ INIT_LIST_HEAD(&fence->base.list);
fence->class = class;
fence->type = type;
fence->flush_mask = 0;
fence->submitted_flush = 0;
fence->signaled = 0;
fence->sequence = 0;
+ fence->dev = dev;
write_unlock_irqrestore(&fm->lock, flags);
if (fence_flags & DRM_FENCE_FLAG_EMIT) {
- ret = drm_fence_object_emit(dev, fence, fence_flags,
+ ret = drm_fence_object_emit(fence, fence_flags,
fence->class, type);
}
return ret;
}
-int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence,
+int drm_fence_add_user_object(struct drm_file * priv, struct drm_fence_object * fence,
int shareable)
{
- drm_device_t *dev = priv->head->dev;
+ struct drm_device *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;
+ goto out;
+ atomic_inc(&fence->usage);
fence->base.type = drm_fence_type;
fence->base.remove = &drm_fence_object_destroy;
DRM_DEBUG("Fence 0x%08lx created\n", fence->base.hash.key);
- return 0;
+out:
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
}
-
EXPORT_SYMBOL(drm_fence_add_user_object);
-int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
- unsigned flags, drm_fence_object_t ** c_fence)
+int drm_fence_object_create(struct drm_device * dev, uint32_t class, uint32_t type,
+ unsigned flags, struct drm_fence_object ** c_fence)
{
- drm_fence_object_t *fence;
+ struct drm_fence_object *fence;
int ret;
- drm_fence_manager_t *fm = &dev->fm;
+ struct drm_fence_manager *fm = &dev->fm;
- fence = drm_ctl_alloc(sizeof(*fence), DRM_MEM_FENCE);
+ fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE);
if (!fence)
return -ENOMEM;
ret = drm_fence_object_init(dev, class, type, flags, fence);
if (ret) {
- drm_fence_usage_deref_unlocked(dev, fence);
+ drm_fence_usage_deref_unlocked(&fence);
return ret;
}
*c_fence = fence;
@@ -488,15 +514,16 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
EXPORT_SYMBOL(drm_fence_object_create);
-void drm_fence_manager_init(drm_device_t * dev)
+void drm_fence_manager_init(struct drm_device * dev)
{
- drm_fence_manager_t *fm = &dev->fm;
- drm_fence_class_manager_t *class;
- drm_fence_driver_t *fed = dev->driver->fence_driver;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_class_manager *class;
+ struct drm_fence_driver *fed = dev->driver->fence_driver;
int i;
+ unsigned long flags;
rwlock_init(&fm->lock);
- write_lock(&fm->lock);
+ write_lock_irqsave(&fm->lock, flags);
fm->initialized = 0;
if (!fed)
goto out_unlock;
@@ -515,18 +542,18 @@ void drm_fence_manager_init(drm_device_t * dev)
atomic_set(&fm->count, 0);
out_unlock:
- write_unlock(&fm->lock);
+ write_unlock_irqrestore(&fm->lock, flags);
}
-void drm_fence_manager_takedown(drm_device_t * dev)
+void drm_fence_manager_takedown(struct drm_device * dev)
{
}
-drm_fence_object_t *drm_lookup_fence_object(drm_file_t * priv, uint32_t handle)
+struct drm_fence_object *drm_lookup_fence_object(struct drm_file * priv, uint32_t handle)
{
- drm_device_t *dev = priv->head->dev;
- drm_user_object_t *uo;
- drm_fence_object_t *fence;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_user_object *uo;
+ struct drm_fence_object *fence;
mutex_lock(&dev->struct_mutex);
uo = drm_lookup_user_object(priv, handle);
@@ -534,20 +561,17 @@ drm_fence_object_t *drm_lookup_fence_object(drm_file_t * priv, uint32_t handle)
mutex_unlock(&dev->struct_mutex);
return NULL;
}
- fence = drm_user_object_entry(uo, drm_fence_object_t, base);
- atomic_inc(&fence->usage);
+ fence = drm_fence_reference_locked(drm_user_object_entry(uo, struct drm_fence_object, base));
mutex_unlock(&dev->struct_mutex);
return fence;
}
-int drm_fence_ioctl(DRM_IOCTL_ARGS)
+int drm_fence_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
- DRM_DEVICE;
int ret;
- drm_fence_manager_t *fm = &dev->fm;
- drm_fence_arg_t arg;
- drm_fence_object_t *fence;
- drm_user_object_t *uo;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ struct drm_fence_object *fence;
unsigned long flags;
ret = 0;
@@ -556,106 +580,265 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
return -EINVAL;
}
- DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
- switch (arg.op) {
- case drm_fence_create:
- if (arg.flags & DRM_FENCE_FLAG_EMIT)
- LOCK_TEST_WITH_RETURN(dev, filp);
- ret = drm_fence_object_create(dev, arg.class,
- arg.type, arg.flags, &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;
- }
+ if (arg->flags & DRM_FENCE_FLAG_EMIT)
+ LOCK_TEST_WITH_RETURN(dev, file_priv);
+ ret = drm_fence_object_create(dev, arg->class,
+ arg->type, arg->flags, &fence);
+ if (ret)
+ return ret;
+ ret = drm_fence_add_user_object(file_priv, fence,
+ arg->flags &
+ DRM_FENCE_FLAG_SHAREABLE);
+ if (ret) {
+ drm_fence_usage_deref_unlocked(&fence);
+ return ret;
+ }
+
+ /*
+ * usage > 0. No need to lock dev->struct_mutex;
+ */
+
+ arg->handle = fence->base.hash.key;
- /*
- * usage > 0. No need to lock dev->struct_mutex;
- */
+ read_lock_irqsave(&fm->lock, flags);
+ arg->class = fence->class;
+ arg->type = fence->type;
+ arg->signaled = fence->signaled;
+ read_unlock_irqrestore(&fm->lock, flags);
+ drm_fence_usage_deref_unlocked(&fence);
- 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);
- if (!uo || (uo->type != drm_fence_type) || uo->owner != priv) {
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
- ret = drm_remove_user_object(priv, uo);
+ return ret;
+}
+
+int drm_fence_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ int ret;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ struct drm_user_object *uo;
+ ret = 0;
+
+ if (!fm->initialized) {
+ DRM_ERROR("The DRM driver does not support fencing.\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->struct_mutex);
+ uo = drm_lookup_user_object(file_priv, arg->handle);
+ if (!uo || (uo->type != drm_fence_type) || uo->owner != file_priv) {
mutex_unlock(&dev->struct_mutex);
+ return -EINVAL;
+ }
+ ret = drm_remove_user_object(file_priv, uo);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+
+int drm_fence_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ int ret;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ struct drm_fence_object *fence;
+ struct drm_user_object *uo;
+ unsigned long flags;
+ ret = 0;
+
+ if (!fm->initialized) {
+ DRM_ERROR("The DRM driver does not support fencing.\n");
+ return -EINVAL;
+ }
+
+ ret = drm_user_object_ref(file_priv, arg->handle, drm_fence_type, &uo);
+ if (ret)
return ret;
- case drm_fence_reference:
- ret =
- drm_user_object_ref(priv, arg.handle, drm_fence_type, &uo);
- if (ret)
- return ret;
- fence = drm_lookup_fence_object(priv, arg.handle);
- break;
- case drm_fence_unreference:
- ret = drm_user_object_unref(priv, arg.handle, drm_fence_type);
- return ret;
- case drm_fence_signaled:
- fence = drm_lookup_fence_object(priv, arg.handle);
- if (!fence)
- return -EINVAL;
- break;
- case drm_fence_flush:
- fence = drm_lookup_fence_object(priv, arg.handle);
- if (!fence)
- return -EINVAL;
- ret = drm_fence_object_flush(dev, fence, arg.type);
- break;
- case drm_fence_wait:
- fence = drm_lookup_fence_object(priv, arg.handle);
- if (!fence)
- return -EINVAL;
- ret =
- drm_fence_object_wait(dev, fence,
- arg.flags & DRM_FENCE_FLAG_WAIT_LAZY,
- 0, arg.type);
- break;
- case drm_fence_emit:
- LOCK_TEST_WITH_RETURN(dev, filp);
- fence = drm_lookup_fence_object(priv, arg.handle);
- if (!fence)
- return -EINVAL;
- ret = drm_fence_object_emit(dev, fence, arg.flags, arg.class,
- 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, arg.flags,
- 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:
+ fence = drm_lookup_fence_object(file_priv, arg->handle);
+
+ read_lock_irqsave(&fm->lock, flags);
+ arg->class = fence->class;
+ arg->type = fence->type;
+ arg->signaled = fence->signaled;
+ read_unlock_irqrestore(&fm->lock, flags);
+ drm_fence_usage_deref_unlocked(&fence);
+
+ return ret;
+}
+
+
+int drm_fence_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ int ret;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ ret = 0;
+
+ if (!fm->initialized) {
+ DRM_ERROR("The DRM driver does not support fencing.\n");
+ return -EINVAL;
+ }
+
+ return drm_user_object_unref(file_priv, arg->handle, drm_fence_type);
+}
+
+int drm_fence_signaled_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ int ret;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ struct drm_fence_object *fence;
+ unsigned long flags;
+ ret = 0;
+
+ if (!fm->initialized) {
+ DRM_ERROR("The DRM driver does not support fencing.\n");
+ return -EINVAL;
+ }
+
+ fence = drm_lookup_fence_object(file_priv, arg->handle);
+ if (!fence)
+ return -EINVAL;
+
+ read_lock_irqsave(&fm->lock, flags);
+ arg->class = fence->class;
+ arg->type = fence->type;
+ arg->signaled = fence->signaled;
+ read_unlock_irqrestore(&fm->lock, flags);
+ drm_fence_usage_deref_unlocked(&fence);
+
+ return ret;
+}
+
+int drm_fence_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ int ret;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ struct drm_fence_object *fence;
+ unsigned long flags;
+ ret = 0;
+
+ if (!fm->initialized) {
+ DRM_ERROR("The DRM driver does not support fencing.\n");
+ return -EINVAL;
+ }
+
+ fence = drm_lookup_fence_object(file_priv, arg->handle);
+ if (!fence)
+ return -EINVAL;
+ ret = drm_fence_object_flush(fence, arg->type);
+
+ read_lock_irqsave(&fm->lock, flags);
+ arg->class = fence->class;
+ arg->type = fence->type;
+ arg->signaled = fence->signaled;
+ read_unlock_irqrestore(&fm->lock, flags);
+ drm_fence_usage_deref_unlocked(&fence);
+
+ return ret;
+}
+
+
+int drm_fence_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ int ret;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ struct drm_fence_object *fence;
+ unsigned long flags;
+ ret = 0;
+
+ if (!fm->initialized) {
+ DRM_ERROR("The DRM driver does not support fencing.\n");
return -EINVAL;
}
+
+ fence = drm_lookup_fence_object(file_priv, arg->handle);
+ if (!fence)
+ return -EINVAL;
+ ret = drm_fence_object_wait(fence,
+ arg->flags & DRM_FENCE_FLAG_WAIT_LAZY,
+ 0, arg->type);
+
+ read_lock_irqsave(&fm->lock, flags);
+ arg->class = fence->class;
+ arg->type = fence->type;
+ arg->signaled = fence->signaled;
+ read_unlock_irqrestore(&fm->lock, flags);
+ drm_fence_usage_deref_unlocked(&fence);
+
+ return ret;
+}
+
+
+int drm_fence_emit_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ int ret;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ struct drm_fence_object *fence;
+ unsigned long flags;
+ ret = 0;
+
+ if (!fm->initialized) {
+ DRM_ERROR("The DRM driver does not support fencing.\n");
+ return -EINVAL;
+ }
+
+ LOCK_TEST_WITH_RETURN(dev, file_priv);
+ fence = drm_lookup_fence_object(file_priv, arg->handle);
+ if (!fence)
+ return -EINVAL;
+ ret = drm_fence_object_emit(fence, arg->flags, arg->class,
+ arg->type);
+
+ read_lock_irqsave(&fm->lock, flags);
+ arg->class = fence->class;
+ arg->type = fence->type;
+ arg->signaled = fence->signaled;
+ read_unlock_irqrestore(&fm->lock, flags);
+ drm_fence_usage_deref_unlocked(&fence);
+
+ return ret;
+}
+
+int drm_fence_buffers_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ int ret;
+ struct drm_fence_manager *fm = &dev->fm;
+ struct drm_fence_arg *arg = data;
+ struct drm_fence_object *fence;
+ unsigned long flags;
+ ret = 0;
+
+ if (!fm->initialized) {
+ DRM_ERROR("The DRM driver does not support fencing.\n");
+ return -EINVAL;
+ }
+
+ if (!dev->bm.initialized) {
+ DRM_ERROR("Buffer object manager is not initialized\n");
+ return -EINVAL;
+ }
+ LOCK_TEST_WITH_RETURN(dev, file_priv);
+ ret = drm_fence_buffer_objects(file_priv, NULL, arg->flags,
+ NULL, &fence);
+ if (ret)
+ return ret;
+ ret = drm_fence_add_user_object(file_priv, fence,
+ arg->flags &
+ DRM_FENCE_FLAG_SHAREABLE);
+ if (ret)
+ return ret;
+
+ arg->handle = fence->base.hash.key;
+
read_lock_irqsave(&fm->lock, flags);
- arg.class = fence->class;
- arg.type = fence->type;
- arg.signaled = fence->signaled;
+ arg->class = fence->class;
+ arg->type = fence->type;
+ arg->signaled = fence->signaled;
read_unlock_irqrestore(&fm->lock, flags);
- drm_fence_usage_deref_unlocked(dev, fence);
+ drm_fence_usage_deref_unlocked(&fence);
- DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));
return ret;
}