diff options
Diffstat (limited to 'linux-core/drm_fence.c')
-rw-r--r-- | linux-core/drm_fence.c | 829 |
1 files changed, 0 insertions, 829 deletions
diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c deleted file mode 100644 index 7c78e09f..00000000 --- a/linux-core/drm_fence.c +++ /dev/null @@ -1,829 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#include "drmP.h" - - -/* - * Convenience function to be called by fence::wait methods that - * need polling. - */ - -int drm_fence_wait_polling(struct drm_fence_object *fence, int lazy, - int interruptible, uint32_t mask, - unsigned long end_jiffies) -{ - struct drm_device *dev = fence->dev; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class]; - uint32_t count = 0; - int ret; - - DECLARE_WAITQUEUE(entry, current); - add_wait_queue(&fc->fence_queue, &entry); - - ret = 0; - - for (;;) { - __set_current_state((interruptible) ? - TASK_INTERRUPTIBLE : - TASK_UNINTERRUPTIBLE); - if (drm_fence_object_signaled(fence, mask)) - break; - if (time_after_eq(jiffies, end_jiffies)) { - ret = -EBUSY; - break; - } - if (lazy) - schedule_timeout(1); - else if ((++count & 0x0F) == 0){ - __set_current_state(TASK_RUNNING); - schedule(); - __set_current_state((interruptible) ? - TASK_INTERRUPTIBLE : - TASK_UNINTERRUPTIBLE); - } - if (interruptible && signal_pending(current)) { - ret = -EAGAIN; - break; - } - } - __set_current_state(TASK_RUNNING); - remove_wait_queue(&fc->fence_queue, &entry); - return ret; -} -EXPORT_SYMBOL(drm_fence_wait_polling); - -/* - * Typically called by the IRQ handler. - */ - -void drm_fence_handler(struct drm_device *dev, uint32_t fence_class, - uint32_t sequence, uint32_t type, uint32_t error) -{ - int wake = 0; - uint32_t diff; - uint32_t relevant_type; - uint32_t new_type; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[fence_class]; - struct drm_fence_driver *driver = dev->driver->fence_driver; - struct list_head *head; - struct drm_fence_object *fence, *next; - int found = 0; - - if (list_empty(&fc->ring)) - return; - - list_for_each_entry(fence, &fc->ring, ring) { - diff = (sequence - fence->sequence) & driver->sequence_mask; - if (diff > driver->wrap_diff) { - found = 1; - break; - } - } - - fc->waiting_types &= ~type; - head = (found) ? &fence->ring : &fc->ring; - - list_for_each_entry_safe_reverse(fence, next, head, ring) { - if (&fence->ring == &fc->ring) - break; - - if (error) { - fence->error = error; - fence->signaled_types = fence->type; - list_del_init(&fence->ring); - wake = 1; - break; - } - - if (type & DRM_FENCE_TYPE_EXE) - type |= fence->native_types; - - relevant_type = type & fence->type; - new_type = (fence->signaled_types | relevant_type) ^ - fence->signaled_types; - - if (new_type) { - fence->signaled_types |= new_type; - DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n", - fence->base.hash.key, fence->signaled_types); - - if (driver->needed_flush) - fc->pending_flush |= driver->needed_flush(fence); - - if (new_type & fence->waiting_types) - wake = 1; - } - - fc->waiting_types |= fence->waiting_types & ~fence->signaled_types; - - if (!(fence->type & ~fence->signaled_types)) { - DRM_DEBUG("Fence completely signaled 0x%08lx\n", - fence->base.hash.key); - list_del_init(&fence->ring); - } - } - - /* - * Reinstate lost waiting types. - */ - - if ((fc->waiting_types & type) != type) { - head = head->prev; - list_for_each_entry(fence, head, ring) { - if (&fence->ring == &fc->ring) - break; - diff = (fc->highest_waiting_sequence - fence->sequence) & - driver->sequence_mask; - if (diff > driver->wrap_diff) - break; - - fc->waiting_types |= fence->waiting_types & ~fence->signaled_types; - } - } - - if (wake) - wake_up_all(&fc->fence_queue); -} -EXPORT_SYMBOL(drm_fence_handler); - -static void drm_fence_unring(struct drm_device *dev, struct list_head *ring) -{ - struct drm_fence_manager *fm = &dev->fm; - unsigned long flags; - - write_lock_irqsave(&fm->lock, flags); - list_del_init(ring); - write_unlock_irqrestore(&fm->lock, flags); -} - -void drm_fence_usage_deref_locked(struct drm_fence_object **fence) -{ - 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", - tmp_fence->base.hash.key); - atomic_dec(&fm->count); - BUG_ON(!list_empty(&tmp_fence->base.list)); - drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE); - } -} -EXPORT_SYMBOL(drm_fence_usage_deref_locked); - -void drm_fence_usage_deref_unlocked(struct drm_fence_object **fence) -{ - struct drm_fence_object *tmp_fence = *fence; - struct drm_device *dev = tmp_fence->dev; - struct drm_fence_manager *fm = &dev->fm; - - *fence = NULL; - if (atomic_dec_and_test(&tmp_fence->usage)) { - mutex_lock(&dev->struct_mutex); - if (atomic_read(&tmp_fence->usage) == 0) { - drm_fence_unring(dev, &tmp_fence->ring); - atomic_dec(&fm->count); - BUG_ON(!list_empty(&tmp_fence->base.list)); - drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE); - } - mutex_unlock(&dev->struct_mutex); - } -} -EXPORT_SYMBOL(drm_fence_usage_deref_unlocked); - -struct drm_fence_object -*drm_fence_reference_locked(struct drm_fence_object *src) -{ - DRM_ASSERT_LOCKED(&src->dev->struct_mutex); - - atomic_inc(&src->usage); - return src; -} - -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); -} -EXPORT_SYMBOL(drm_fence_reference_unlocked); - -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) -{ - unsigned long flags; - int signaled; - struct drm_device *dev = fence->dev; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_driver *driver = dev->driver->fence_driver; - - mask &= fence->type; - read_lock_irqsave(&fm->lock, flags); - signaled = (mask & fence->signaled_types) == mask; - read_unlock_irqrestore(&fm->lock, flags); - if (!signaled && driver->poll) { - write_lock_irqsave(&fm->lock, flags); - driver->poll(dev, fence->fence_class, mask); - signaled = (mask & fence->signaled_types) == mask; - write_unlock_irqrestore(&fm->lock, flags); - } - return signaled; -} -EXPORT_SYMBOL(drm_fence_object_signaled); - - -int drm_fence_object_flush(struct drm_fence_object *fence, - uint32_t type) -{ - struct drm_device *dev = fence->dev; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class]; - struct drm_fence_driver *driver = dev->driver->fence_driver; - unsigned long irq_flags; - uint32_t saved_pending_flush; - uint32_t diff; - int call_flush; - - if (type & ~fence->type) { - DRM_ERROR("Flush trying to extend fence type, " - "0x%x, 0x%x\n", type, fence->type); - return -EINVAL; - } - - write_lock_irqsave(&fm->lock, irq_flags); - fence->waiting_types |= type; - fc->waiting_types |= fence->waiting_types; - diff = (fence->sequence - fc->highest_waiting_sequence) & - driver->sequence_mask; - - if (diff < driver->wrap_diff) - fc->highest_waiting_sequence = fence->sequence; - - /* - * fence->waiting_types has changed. Determine whether - * we need to initiate some kind of flush as a result of this. - */ - - saved_pending_flush = fc->pending_flush; - if (driver->needed_flush) - fc->pending_flush |= driver->needed_flush(fence); - - if (driver->poll) - driver->poll(dev, fence->fence_class, fence->waiting_types); - - call_flush = fc->pending_flush; - write_unlock_irqrestore(&fm->lock, irq_flags); - - if (call_flush && driver->flush) - driver->flush(dev, fence->fence_class); - - return 0; -} -EXPORT_SYMBOL(drm_fence_object_flush); - -/* - * Make sure old fence objects are signaled before their fence sequences are - * wrapped around and reused. - */ - -void drm_fence_flush_old(struct drm_device *dev, uint32_t fence_class, - uint32_t sequence) -{ - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[fence_class]; - struct drm_fence_object *fence; - unsigned long irq_flags; - struct drm_fence_driver *driver = dev->driver->fence_driver; - int call_flush; - - uint32_t diff; - - write_lock_irqsave(&fm->lock, irq_flags); - - list_for_each_entry_reverse(fence, &fc->ring, ring) { - diff = (sequence - fence->sequence) & driver->sequence_mask; - if (diff <= driver->flush_diff) - break; - - fence->waiting_types = fence->type; - fc->waiting_types |= fence->type; - - if (driver->needed_flush) - fc->pending_flush |= driver->needed_flush(fence); - } - - if (driver->poll) - driver->poll(dev, fence_class, fc->waiting_types); - - call_flush = fc->pending_flush; - write_unlock_irqrestore(&fm->lock, irq_flags); - - if (call_flush && driver->flush) - driver->flush(dev, fence->fence_class); - - /* - * FIXME: Shold we implement a wait here for really old fences? - */ - -} -EXPORT_SYMBOL(drm_fence_flush_old); - -int drm_fence_object_wait(struct drm_fence_object *fence, - int lazy, int ignore_signals, uint32_t mask) -{ - struct drm_device *dev = fence->dev; - struct drm_fence_driver *driver = dev->driver->fence_driver; - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class]; - int ret = 0; - unsigned long _end = 3 * DRM_HZ; - - if (mask & ~fence->type) { - DRM_ERROR("Wait trying to extend fence type" - " 0x%08x 0x%08x\n", mask, fence->type); - BUG(); - return -EINVAL; - } - - if (driver->wait) - return driver->wait(fence, lazy, !ignore_signals, mask); - - - drm_fence_object_flush(fence, mask); - if (driver->has_irq(dev, fence->fence_class, mask)) { - if (!ignore_signals) - ret = wait_event_interruptible_timeout - (fc->fence_queue, - drm_fence_object_signaled(fence, mask), - 3 * DRM_HZ); - else - ret = wait_event_timeout - (fc->fence_queue, - drm_fence_object_signaled(fence, mask), - 3 * DRM_HZ); - - if (unlikely(ret == -ERESTARTSYS)) - return -EAGAIN; - - if (unlikely(ret == 0)) - return -EBUSY; - - return 0; - } - - return drm_fence_wait_polling(fence, lazy, !ignore_signals, mask, - _end); -} -EXPORT_SYMBOL(drm_fence_object_wait); - - - -int drm_fence_object_emit(struct drm_fence_object *fence, uint32_t fence_flags, - uint32_t fence_class, uint32_t type) -{ - 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->fence_class[fence->fence_class]; - unsigned long flags; - uint32_t sequence; - uint32_t native_types; - int ret; - - drm_fence_unring(dev, &fence->ring); - ret = driver->emit(dev, fence_class, fence_flags, &sequence, - &native_types); - if (ret) - return ret; - - write_lock_irqsave(&fm->lock, flags); - fence->fence_class = fence_class; - fence->type = type; - fence->waiting_types = 0; - fence->signaled_types = 0; - fence->error = 0; - fence->sequence = sequence; - fence->native_types = native_types; - if (list_empty(&fc->ring)) - fc->highest_waiting_sequence = sequence - 1; - list_add_tail(&fence->ring, &fc->ring); - fc->latest_queued_sequence = sequence; - write_unlock_irqrestore(&fm->lock, flags); - return 0; -} -EXPORT_SYMBOL(drm_fence_object_emit); - -static int drm_fence_object_init(struct drm_device *dev, uint32_t fence_class, - uint32_t type, - uint32_t fence_flags, - struct drm_fence_object *fence) -{ - int ret = 0; - unsigned long flags; - struct drm_fence_manager *fm = &dev->fm; - - mutex_lock(&dev->struct_mutex); - atomic_set(&fence->usage, 1); - mutex_unlock(&dev->struct_mutex); - - 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->fence_class = fence_class; - fence->type = type; - fence->signaled_types = 0; - fence->waiting_types = 0; - fence->sequence = 0; - fence->error = 0; - fence->dev = dev; - write_unlock_irqrestore(&fm->lock, flags); - if (fence_flags & DRM_FENCE_FLAG_EMIT) { - ret = drm_fence_object_emit(fence, fence_flags, - fence->fence_class, type); - } - return ret; -} - -int drm_fence_add_user_object(struct drm_file *priv, - struct drm_fence_object *fence, int shareable) -{ - struct drm_device *dev = priv->minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm_add_user_object(priv, &fence->base, shareable); - if (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); -out: - mutex_unlock(&dev->struct_mutex); - return ret; -} -EXPORT_SYMBOL(drm_fence_add_user_object); - -int drm_fence_object_create(struct drm_device *dev, uint32_t fence_class, - uint32_t type, unsigned flags, - struct drm_fence_object **c_fence) -{ - struct drm_fence_object *fence; - int ret; - struct drm_fence_manager *fm = &dev->fm; - - fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE); - if (!fence) { - DRM_ERROR("Out of memory creating fence object\n"); - return -ENOMEM; - } - ret = drm_fence_object_init(dev, fence_class, type, flags, fence); - if (ret) { - drm_fence_usage_deref_unlocked(&fence); - return ret; - } - *c_fence = fence; - atomic_inc(&fm->count); - - return 0; -} -EXPORT_SYMBOL(drm_fence_object_create); - -void drm_fence_manager_init(struct drm_device *dev) -{ - struct drm_fence_manager *fm = &dev->fm; - struct drm_fence_class_manager *fence_class; - struct drm_fence_driver *fed = dev->driver->fence_driver; - int i; - unsigned long flags; - - rwlock_init(&fm->lock); - write_lock_irqsave(&fm->lock, flags); - fm->initialized = 0; - if (!fed) - goto out_unlock; - - fm->initialized = 1; - fm->num_classes = fed->num_classes; - BUG_ON(fm->num_classes > _DRM_FENCE_CLASSES); - - for (i = 0; i < fm->num_classes; ++i) { - fence_class = &fm->fence_class[i]; - - memset(fence_class, 0, sizeof(*fence_class)); - INIT_LIST_HEAD(&fence_class->ring); - DRM_INIT_WAITQUEUE(&fence_class->fence_queue); - } - - atomic_set(&fm->count, 0); - out_unlock: - write_unlock_irqrestore(&fm->lock, flags); -} - -void drm_fence_fill_arg(struct drm_fence_object *fence, - struct drm_fence_arg *arg) -{ - struct drm_device *dev = fence->dev; - struct drm_fence_manager *fm = &dev->fm; - unsigned long irq_flags; - - read_lock_irqsave(&fm->lock, irq_flags); - arg->handle = fence->base.hash.key; - arg->fence_class = fence->fence_class; - arg->type = fence->type; - arg->signaled = fence->signaled_types; - arg->error = fence->error; - arg->sequence = fence->sequence; - read_unlock_irqrestore(&fm->lock, irq_flags); -} -EXPORT_SYMBOL(drm_fence_fill_arg); - -void drm_fence_manager_takedown(struct drm_device *dev) -{ -} - -struct drm_fence_object *drm_lookup_fence_object(struct drm_file *priv, - uint32_t handle) -{ - struct drm_device *dev = priv->minor->dev; - struct drm_user_object *uo; - struct drm_fence_object *fence; - - mutex_lock(&dev->struct_mutex); - uo = drm_lookup_user_object(priv, handle); - if (!uo || (uo->type != drm_fence_type)) { - mutex_unlock(&dev->struct_mutex); - return NULL; - } - 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_create_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; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - if (arg->flags & DRM_FENCE_FLAG_EMIT) - LOCK_TEST_WITH_RETURN(dev, file_priv); - ret = drm_fence_object_create(dev, arg->fence_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; - - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - 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; - 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; - fence = drm_lookup_fence_object(file_priv, arg->handle); - drm_fence_fill_arg(fence, arg); - 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; - 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; - - drm_fence_fill_arg(fence, arg); - 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; - 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); - - drm_fence_fill_arg(fence, arg); - 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; - 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); - - drm_fence_fill_arg(fence, arg); - 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; - 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->fence_class, - arg->type); - - drm_fence_fill_arg(fence, arg); - 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; - 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(dev, NULL, arg->flags, - NULL, &fence); - if (ret) - return ret; - - if (!(arg->flags & DRM_FENCE_FLAG_NO_USER)) { - 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; - - drm_fence_fill_arg(fence, arg); - drm_fence_usage_deref_unlocked(&fence); - - return ret; -} |