From 3dfc1400e9fc58c69292d7cf7c2e1653fa5e6991 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 6 May 2007 11:35:11 +1000 Subject: drm/ttm: cleanup most of fence ioctl split out --- linux-core/drm_fence.c | 310 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index ce161dc3..fe11e87b 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -659,3 +659,313 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); return ret; } + +int drm_fence_create_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + int ret; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_arg_t arg; + drm_fence_object_t *fence; + unsigned long flags; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + + 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; + } + + /* + * usage > 0. No need to lock dev->struct_mutex; + */ + + atomic_inc(&fence->usage); + arg.handle = fence->base.hash.key; + + 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(dev, fence); + + DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); + return ret; +} + +int drm_fence_destroy_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + int ret; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_arg_t arg; + drm_user_object_t *uo; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + + 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); + mutex_unlock(&dev->struct_mutex); + return ret; +} + + +int drm_fence_reference_ioctl(DRM_IOCTL_ARGS) +{ + 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; + unsigned long flags; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + ret = drm_user_object_ref(priv, arg.handle, drm_fence_type, &uo); + if (ret) + return ret; + fence = drm_lookup_fence_object(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(dev, fence); + + DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); + return ret; +} + + +int drm_fence_unreference_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + int ret; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_arg_t arg; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + return drm_user_object_unref(priv, arg.handle, drm_fence_type); +} + +int drm_fence_signaled_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + int ret; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_arg_t arg; + drm_fence_object_t *fence; + unsigned long flags; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + + fence = drm_lookup_fence_object(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(dev, fence); + + DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); + return ret; +} + +int drm_fence_flush_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + int ret; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_arg_t arg; + drm_fence_object_t *fence; + unsigned long flags; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + + fence = drm_lookup_fence_object(priv, arg.handle); + if (!fence) + return -EINVAL; + ret = drm_fence_object_flush(dev, 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(dev, fence); + + DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); + return ret; +} + + +int drm_fence_wait_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + int ret; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_arg_t arg; + drm_fence_object_t *fence; + unsigned long flags; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + + 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); + + 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(dev, fence); + + DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); + return ret; +} + + +int drm_fence_emit_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + int ret; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_arg_t arg; + drm_fence_object_t *fence; + unsigned long flags; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + + 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); + + 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(dev, fence); + + DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); + return ret; +} + +int drm_fence_buffers_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + int ret; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_arg_t arg; + drm_fence_object_t *fence; + unsigned long flags; + ret = 0; + + if (!fm->initialized) { + DRM_ERROR("The DRM driver does not support fencing.\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + + 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; + + 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(dev, fence); + + DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); + return ret; +} -- cgit v1.2.3 From 375f3f2884cd1437e9ec2608647face0c3cbef3a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 26 May 2007 03:47:48 +1000 Subject: Revert "drm/ttm: cleanup most of fence ioctl split out" This reverts commit 3dfc1400e9fc58c69292d7cf7c2e1653fa5e6991. this shouldn't have gone on master yet --- linux-core/drm_fence.c | 310 ------------------------------------------------- 1 file changed, 310 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index fe11e87b..ce161dc3 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -659,313 +659,3 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); return ret; } - -int drm_fence_create_ioctl(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - int ret; - drm_fence_manager_t *fm = &dev->fm; - drm_fence_arg_t arg; - drm_fence_object_t *fence; - unsigned long flags; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - - 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; - } - - /* - * usage > 0. No need to lock dev->struct_mutex; - */ - - atomic_inc(&fence->usage); - arg.handle = fence->base.hash.key; - - 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(dev, fence); - - DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); - return ret; -} - -int drm_fence_destroy_ioctl(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - int ret; - drm_fence_manager_t *fm = &dev->fm; - drm_fence_arg_t arg; - drm_user_object_t *uo; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - - 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); - mutex_unlock(&dev->struct_mutex); - return ret; -} - - -int drm_fence_reference_ioctl(DRM_IOCTL_ARGS) -{ - 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; - unsigned long flags; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - ret = drm_user_object_ref(priv, arg.handle, drm_fence_type, &uo); - if (ret) - return ret; - fence = drm_lookup_fence_object(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(dev, fence); - - DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); - return ret; -} - - -int drm_fence_unreference_ioctl(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - int ret; - drm_fence_manager_t *fm = &dev->fm; - drm_fence_arg_t arg; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - return drm_user_object_unref(priv, arg.handle, drm_fence_type); -} - -int drm_fence_signaled_ioctl(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - int ret; - drm_fence_manager_t *fm = &dev->fm; - drm_fence_arg_t arg; - drm_fence_object_t *fence; - unsigned long flags; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - - fence = drm_lookup_fence_object(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(dev, fence); - - DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); - return ret; -} - -int drm_fence_flush_ioctl(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - int ret; - drm_fence_manager_t *fm = &dev->fm; - drm_fence_arg_t arg; - drm_fence_object_t *fence; - unsigned long flags; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - - fence = drm_lookup_fence_object(priv, arg.handle); - if (!fence) - return -EINVAL; - ret = drm_fence_object_flush(dev, 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(dev, fence); - - DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); - return ret; -} - - -int drm_fence_wait_ioctl(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - int ret; - drm_fence_manager_t *fm = &dev->fm; - drm_fence_arg_t arg; - drm_fence_object_t *fence; - unsigned long flags; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - - 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); - - 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(dev, fence); - - DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); - return ret; -} - - -int drm_fence_emit_ioctl(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - int ret; - drm_fence_manager_t *fm = &dev->fm; - drm_fence_arg_t arg; - drm_fence_object_t *fence; - unsigned long flags; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - - 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); - - 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(dev, fence); - - DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); - return ret; -} - -int drm_fence_buffers_ioctl(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - int ret; - drm_fence_manager_t *fm = &dev->fm; - drm_fence_arg_t arg; - drm_fence_object_t *fence; - unsigned long flags; - ret = 0; - - if (!fm->initialized) { - DRM_ERROR("The DRM driver does not support fencing.\n"); - return -EINVAL; - } - - DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); - - 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; - - 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(dev, fence); - - DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); - return ret; -} -- cgit v1.2.3 From 62082ab3e63f6f474655da98b710e453b4124ed1 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jun 2007 15:38:59 +0200 Subject: Make sure we read fence->signaled while spinlocked. --- linux-core/drm_fence.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index ce161dc3..70baad9f 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -164,7 +164,7 @@ static void drm_fence_object_destroy(drm_file_t * priv, drm_fence_usage_deref_locked(dev, fence); } -static int fence_signaled(drm_device_t * dev, +int drm_fence_object_signaled(drm_device_t * dev, drm_fence_object_t * fence, uint32_t mask, int poke_flush) { @@ -200,12 +200,6 @@ 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, uint32_t type) @@ -298,13 +292,13 @@ static int drm_fence_lazy_wait(drm_device_t *dev, do { DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ, - (signaled = fence_signaled(dev, fence, mask, 1))); + (signaled = drm_fence_object_signaled(dev, 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(dev, fence, mask, 0)) return 0; if (time_after_eq(jiffies, _end)) ret = -EBUSY; @@ -334,7 +328,7 @@ int drm_fence_object_wait(drm_device_t * dev, return -EINVAL; } - if (fence_signaled(dev, fence, mask, 0)) + if (drm_fence_object_signaled(dev, fence, mask, 0)) return 0; _end = jiffies + 3 * DRM_HZ; @@ -365,7 +359,7 @@ int drm_fence_object_wait(drm_device_t * dev, return ret; } } - if (drm_fence_object_signaled(fence, mask)) + if (drm_fence_object_signaled(dev, fence, mask, 0)) return 0; /* @@ -377,7 +371,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(dev, fence, mask, 1); } while (!signaled && !time_after_eq(jiffies, _end)); if (!signaled) -- cgit v1.2.3 From e1b8eabeee354822fc0a413dd097210b621eb73a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 14 Jun 2007 11:52:38 +0200 Subject: Locking fixes and instrumentation. --- linux-core/drm_fence.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 70baad9f..b5fc2235 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -129,11 +129,14 @@ void drm_fence_usage_deref_locked(drm_device_t * dev, { drm_fence_manager_t *fm = &dev->fm; + DRM_ASSERT_LOCKED(&dev->struct_mutex); + if (atomic_dec_and_test(&fence->usage)) { drm_fence_unring(dev, &fence->ring); DRM_DEBUG("Destroyed a fence object 0x%08lx\n", fence->base.hash.key); atomic_dec(&fm->count); + BUG_ON(!list_empty(&fence->base.list)); drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE); } } @@ -148,6 +151,7 @@ void drm_fence_usage_deref_unlocked(drm_device_t * dev, if (atomic_read(&fence->usage) == 0) { drm_fence_unring(dev, &fence->ring); atomic_dec(&fm->count); + BUG_ON(!list_empty(&fence->base.list)); drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE); } mutex_unlock(&dev->struct_mutex); @@ -448,15 +452,16 @@ int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence, 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, @@ -466,7 +471,7 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type, int ret; drm_fence_manager_t *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); @@ -566,13 +571,8 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) 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); @@ -637,7 +637,6 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) DRM_FENCE_FLAG_SHAREABLE); if (ret) return ret; - atomic_inc(&fence->usage); arg.handle = fence->base.hash.key; break; default: -- cgit v1.2.3 From 00f1a66f22d52c212bb9334a0103a4785af69bc1 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 29 Jun 2007 12:50:12 +0200 Subject: Fence object reference / dereference cleanup. Buffer object dereference cleanup. Add a struct drm_device member to fence objects: This can simplify code, particularly in drivers. --- linux-core/drm_fence.c | 122 ++++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 51 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index b5fc2235..ace70d51 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -124,56 +124,76 @@ 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(drm_fence_object_t ** fence) { + struct drm_fence_object *tmp_fence = *fence; + struct drm_device *dev = tmp_fence->dev; drm_fence_manager_t *fm = &dev->fm; DRM_ASSERT_LOCKED(&dev->struct_mutex); - - if (atomic_dec_and_test(&fence->usage)) { - drm_fence_unring(dev, &fence->ring); + *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); - BUG_ON(!list_empty(&fence->base.list)); - 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(drm_fence_object_t ** fence) { + struct drm_fence_object *tmp_fence = *fence; + struct drm_device *dev = tmp_fence->dev; drm_fence_manager_t *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); - BUG_ON(!list_empty(&fence->base.list)); - 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_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); +} + + +static void drm_fence_object_destroy(drm_file_t *priv, drm_user_object_t * base) { - drm_device_t *dev = priv->head->dev; drm_fence_object_t *fence = drm_user_object_entry(base, drm_fence_object_t, base); - drm_fence_usage_deref_locked(dev, fence); + drm_fence_usage_deref_locked(&fence); } -int drm_fence_object_signaled(drm_device_t * dev, - drm_fence_object_t * fence, - uint32_t mask, int poke_flush) +int drm_fence_object_signaled(drm_fence_object_t * fence, + uint32_t mask, int poke_flush) { unsigned long flags; int signaled; + struct drm_device *dev = fence->dev; drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; @@ -204,10 +224,10 @@ static void drm_fence_flush_exe(drm_fence_class_manager_t * fc, } } -int drm_fence_object_flush(drm_device_t * dev, - drm_fence_object_t * fence, +int drm_fence_object_flush(drm_fence_object_t * fence, uint32_t type) { + struct drm_device *dev = fence->dev; 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; @@ -270,24 +290,23 @@ 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, drm_fence_object_t, 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(drm_fence_object_t *fence, int ignore_signals, uint32_t mask) { + struct drm_device *dev = fence->dev; drm_fence_manager_t *fm = &dev->fm; drm_fence_class_manager_t *fc = &fm->class[fence->class]; int signaled; @@ -296,13 +315,13 @@ static int drm_fence_lazy_wait(drm_device_t *dev, do { DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ, - (signaled = drm_fence_object_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 (drm_fence_object_signaled(dev, fence, mask, 0)) + if (drm_fence_object_signaled(fence, mask, 0)) return 0; if (time_after_eq(jiffies, _end)) ret = -EBUSY; @@ -317,10 +336,10 @@ 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(drm_fence_object_t * fence, int lazy, int ignore_signals, uint32_t mask) { + struct drm_device *dev = fence->dev; drm_fence_driver_t *driver = dev->driver->fence_driver; int ret = 0; unsigned long _end; @@ -332,16 +351,16 @@ int drm_fence_object_wait(drm_device_t * dev, return -EINVAL; } - if (drm_fence_object_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; @@ -349,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; @@ -357,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(dev, fence, mask, 0)) + if (drm_fence_object_signaled(fence, mask, 0)) return 0; /* @@ -375,7 +394,7 @@ int drm_fence_object_wait(drm_device_t * dev, #endif do { schedule(); - signaled = drm_fence_object_signaled(dev, fence, mask, 1); + signaled = drm_fence_object_signaled(fence, mask, 1); } while (!signaled && !time_after_eq(jiffies, _end)); if (!signaled) @@ -384,9 +403,10 @@ 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(drm_fence_object_t * fence, uint32_t fence_flags, uint32_t class, uint32_t type) { + struct drm_device *dev = fence->dev; 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]; @@ -436,9 +456,10 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t class, 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; @@ -476,7 +497,7 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type, 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; @@ -533,8 +554,7 @@ 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, drm_fence_object_t, base)); mutex_unlock(&dev->struct_mutex); return fence; } @@ -568,7 +588,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) arg.flags & DRM_FENCE_FLAG_SHAREABLE); if (ret) { - drm_fence_usage_deref_unlocked(dev, fence); + drm_fence_usage_deref_unlocked(&fence); return ret; } arg.handle = fence->base.hash.key; @@ -603,14 +623,14 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) fence = drm_lookup_fence_object(priv, arg.handle); if (!fence) return -EINVAL; - ret = drm_fence_object_flush(dev, fence, arg.type); + ret = drm_fence_object_flush(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, + drm_fence_object_wait(fence, arg.flags & DRM_FENCE_FLAG_WAIT_LAZY, 0, arg.type); break; @@ -619,7 +639,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) fence = drm_lookup_fence_object(priv, arg.handle); if (!fence) return -EINVAL; - ret = drm_fence_object_emit(dev, fence, arg.flags, arg.class, + ret = drm_fence_object_emit(fence, arg.flags, arg.class, arg.type); break; case drm_fence_buffers: @@ -647,7 +667,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) 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; -- cgit v1.2.3 From a27af4c4a665864df09123f177ca7269e48f6171 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 29 Jun 2007 15:22:28 +0200 Subject: Avoid hitting BUG() for kernel-only fence objects. --- linux-core/drm_fence.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index ace70d51..5215feb6 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -450,6 +450,12 @@ 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; -- cgit v1.2.3