From 166da9355d95affe427a6cff3525df60e80a99df Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 21 Aug 2006 21:02:08 +0200 Subject: User / Kernel space fence objects (device-independent part). --- linux-core/drm_fence.c | 587 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 587 insertions(+) create mode 100644 linux-core/drm_fence.c (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c new file mode 100644 index 00000000..fc27c576 --- /dev/null +++ b/linux-core/drm_fence.c @@ -0,0 +1,587 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., 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 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ +/* + * Authors: Thomas Hellström + */ + +#include "drmP.h" + +static void drm_fm_update_pointers(drm_fence_manager_t * fm, + struct list_head *list, int no_types, + uint32_t type) +{ + int i; + for (i = 0; i < no_types; ++i) { + if (type & (1 << i)) { + fm->fence_types[i] = list; + } + } +} + +/* + * Typically called by the IRQ handler. + */ + +void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) +{ + int i; + int wake = 0; + int largest = 0; + uint32_t diff; + uint32_t relevant; + int index = 0; + drm_fence_manager_t *fm = &dev->fm; + drm_fence_driver_t *driver = dev->driver->fence_driver; + struct list_head *list; + struct list_head *fence_list; + drm_fence_object_t *fence; + int found = 0; + + for (i = 0; i < driver->no_types; ++i) { + if (!(type & (1 << i))) + continue; + + list = fm->fence_types[i]; + fence_list = list->next; + + if (fence_list == &fm->ring) + continue; + + fence = list_entry(fence_list, drm_fence_object_t, ring); + + diff = (sequence - fence->sequence) & driver->sequence_mask; + + if (diff < driver->wrap_diff) { + if (diff >= largest) { + largest = diff; + index = i; + found = 1; + } + } + } + + if (!found) + return; + + /* + * Start with the fence object with the lowest sequence number, affected by + * the type mask of this call. Update signaled fields, + * Check if we need to wake sleeping processes + */ + + list = fm->fence_types[index]->next; + do { + if (list == &fm->ring) { + drm_fm_update_pointers(fm, list->prev, + driver->no_types, type); + break; + } + fence = list_entry(list, drm_fence_object_t, ring); + diff = (sequence - fence->sequence) & driver->sequence_mask; + if (diff >= driver->wrap_diff) { + drm_fm_update_pointers(fm, fence->ring.prev, + driver->no_types, type); + break; + } + relevant = type & fence->type; + if ((fence->signaled | relevant) != fence->signaled) { + fence->signaled |= relevant; + fence->submitted_flush |= relevant; + wake = 1; + } + + relevant = fence->flush_mask & + ~(fence->signaled | fence->submitted_flush); + if (relevant) { + fm->pending_flush |= relevant; + fence->submitted_flush = fence->flush_mask; + } + + list = list->next; + + /* + * Remove a completely signaled fence from the + * fence manager ring. + */ + + if (!(fence->type & ~fence->signaled)) { + fence_list = &fence->ring; + for (i = 0; i < driver->no_types; ++i) { + if (fm->fence_types[i] == fence_list) + fm->fence_types[i] = fence_list->prev; + } + list_del_init(fence_list); + } + + } while (1); + + /* + * Wake sleeping processes. + */ + + if (wake) { + DRM_WAKEUP(&fm->fence_queue); + } +} + +EXPORT_SYMBOL(drm_fence_handler); + +static void drm_fence_unring(drm_device_t * dev, struct list_head *ring) +{ + drm_fence_manager_t *fm = &dev->fm; + drm_fence_driver_t *driver = dev->driver->fence_driver; + unsigned long flags; + int i; + + write_lock_irqsave(&fm->lock, flags); + for (i = 0; i < driver->no_types; ++i) { + if (fm->fence_types[i] == ring) + fm->fence_types[i] = ring->prev; + } + list_del_init(ring); + write_unlock_irqrestore(&fm->lock, flags); +} + +void drm_fence_usage_deref_locked(drm_device_t * dev, + drm_fence_object_t * fence) +{ + if (atomic_dec_and_test(&fence->usage)) { + drm_fence_unring(dev, &fence->ring); + drm_free(fence, sizeof(*fence), DRM_MEM_FENCE); + } +} + +void drm_fence_usage_deref_unlocked(drm_device_t * dev, + drm_fence_object_t * fence) +{ + if (atomic_dec_and_test(&fence->usage)) { + mutex_lock(&dev->struct_mutex); + if (atomic_read(&fence->usage) == 0) { + drm_fence_unring(dev, &fence->ring); + drm_free(fence, sizeof(*fence), DRM_MEM_FENCE); + } + mutex_unlock(&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); +} + +static int fence_signaled(drm_device_t * dev, drm_fence_object_t * 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; + + if (poke_flush) + driver->poke_flush(dev); + read_lock_irqsave(&fm->lock, flags); + signaled = + (fence->type & mask & fence->signaled) == (fence->type & mask); + read_unlock_irqrestore(&fm->lock, flags); + + return signaled; +} + +static void drm_fence_flush_exe(drm_fence_manager_t * fm, + drm_fence_driver_t * driver, uint32_t sequence) +{ + uint32_t diff; + + if (!fm->pending_exe_flush) { + struct list_head *list; + + /* + * Last_exe_flush is invalid. Find oldest sequence. + */ + + list = fm->fence_types[_DRM_FENCE_TYPE_EXE]; + if (list->next == &fm->ring) { + return; + } else { + drm_fence_object_t *fence = + list_entry(list->next, drm_fence_object_t, ring); + fm->last_exe_flush = (fence->sequence - 1) & + driver->sequence_mask; + } + diff = (sequence - fm->last_exe_flush) & driver->sequence_mask; + if (diff >= driver->wrap_diff) + return; + fm->exe_flush_sequence = sequence; + fm->pending_exe_flush = 1; + } else { + diff = + (sequence - fm->exe_flush_sequence) & driver->sequence_mask; + if (diff < driver->wrap_diff) { + fm->exe_flush_sequence = sequence; + } + } +} + +/* + * Make sure old fence objects are signaled before their fence sequences are + * wrapped around and reused. + */ + +static int drm_fence_object_flush(drm_device_t * dev, + drm_fence_object_t * fence, uint32_t type) +{ + drm_fence_manager_t *fm = &dev->fm; + drm_fence_driver_t *driver = dev->driver->fence_driver; + unsigned long flags; + + if (type & ~fence->type) { + DRM_ERROR("Flush trying to extend fence type\n"); + return -EINVAL; + } + + write_lock_irqsave(&fm->lock, flags); + fence->flush_mask |= type; + if (fence->submitted_flush == fence->signaled) { + if ((fence->type & DRM_FENCE_EXE) && + !(fence->submitted_flush & DRM_FENCE_EXE)) { + drm_fence_flush_exe(fm, driver, fence->sequence); + fence->submitted_flush |= DRM_FENCE_EXE; + } else { + fm->pending_flush |= (fence->flush_mask & + ~fence->submitted_flush); + fence->submitted_flush = fence->flush_mask; + } + } + write_unlock_irqrestore(&fm->lock, flags); + driver->poke_flush(dev); + return 0; +} + +void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence) +{ + drm_fence_manager_t *fm = &dev->fm; + drm_fence_driver_t *driver = dev->driver->fence_driver; + uint32_t old_sequence; + unsigned long flags; + drm_fence_object_t *fence; + uint32_t diff; + + mutex_lock(&dev->struct_mutex); + read_lock_irqsave(&fm->lock, flags); + if (fm->ring.next == &fm->ring) { + read_unlock_irqrestore(&fm->lock, flags); + mutex_unlock(&dev->struct_mutex); + return; + } + old_sequence = (sequence - driver->flush_diff) & driver->sequence_mask; + fence = list_entry(fm->ring.next, drm_fence_object_t, ring); + atomic_inc(&fence->usage); + 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_usage_deref_unlocked(dev, fence); +} + +EXPORT_SYMBOL(drm_fence_flush_old); + +static int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, + int lazy, int ignore_signals, uint32_t mask) +{ + drm_fence_manager_t *fm = &dev->fm; + drm_fence_driver_t *driver = dev->driver->fence_driver; + int ret = 0; + unsigned long _end; + + if (mask & ~fence->type) { + DRM_ERROR("Wait trying to extend fence type\n"); + return -EINVAL; + } + + if (fence_signaled(dev, fence, mask, 0)) + return 0; + + _end = jiffies + 3 * DRM_HZ; + + drm_fence_object_flush(dev, fence, mask); + if (lazy && driver->lazy_capable) { + do { + DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, + fence_signaled(dev, fence, mask, 1)); + if (time_after_eq(jiffies, _end)) + break; + } while (ret == -EINTR && ignore_signals); + + if (time_after_eq(jiffies, _end) && (ret != 0)) + ret = -EBUSY; + return ret; + + } else { + int signaled; + do { + signaled = fence_signaled(dev, fence, mask, 1); + } while (!signaled && !time_after_eq(jiffies, _end)); + if (!signaled) + return -EBUSY; + } + return 0; +} + +int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence, + uint32_t type) +{ + drm_fence_manager_t *fm = &dev->fm; + drm_fence_driver_t *driver = dev->driver->fence_driver; + unsigned long flags; + uint32_t sequence; + int ret; + + drm_fence_unring(dev, &fence->ring); + ret = driver->emit(dev, &sequence); + if (ret) + return ret; + + write_lock_irqsave(&fm->lock, flags); + fence->type = type; + fence->flush_mask = 0x00; + fence->submitted_flush = 0x00; + fence->signaled = 0x00; + fence->sequence = sequence; + list_add_tail(&fence->ring, &fm->ring); + write_unlock_irqrestore(&fm->lock, flags); + return 0; +} + +int drm_fence_object_init(drm_device_t * dev, uint32_t type, int emit, + drm_fence_object_t * fence) +{ + int ret = 0; + unsigned long flags; + drm_fence_manager_t *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); + fence->type = type; + fence->flush_mask = 0; + fence->submitted_flush = 0; + fence->signaled = 0; + fence->sequence = 0; + write_unlock_irqrestore(&fm->lock, flags); + if (emit) { + ret = drm_fence_object_emit(dev, fence, type); + } + return ret; +} + +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) +{ + drm_device_t *dev = priv->head->dev; + int ret; + drm_fence_object_t *fence; + + fence = drm_calloc(1, sizeof(*fence), DRM_MEM_FENCE); + if (!fence) + return -ENOMEM; + ret = drm_fence_object_init(dev, type, emit, fence); + if (ret) { + 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; + + return 0; +} + +void drm_fence_manager_init(drm_device_t * dev) +{ + drm_fence_manager_t *fm = &dev->fm; + drm_fence_driver_t *fed = dev->driver->fence_driver; + int i; + + fm->lock = RW_LOCK_UNLOCKED; + INIT_LIST_HEAD(&fm->ring); + fm->pending_flush = 0; + DRM_INIT_WAITQUEUE(&fm->fence_queue); + fm->initialized = 0; + if (fed) { + fm->initialized = 1; + for (i = 0; i < fed->no_types; ++i) { + fm->fence_types[i] = &fm->ring; + } + } +} + +void drm_fence_manager_takedown(drm_device_t * dev) +{ +} + +drm_fence_object_t *drm_lookup_fence_object(drm_file_t * priv, uint32_t handle) +{ + drm_device_t *dev = priv->head->dev; + drm_user_object_t *uo; + drm_fence_object_t *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_user_object_entry(uo, drm_fence_object_t, base); + atomic_inc(&fence->usage); + mutex_unlock(&dev->struct_mutex); + return fence; +} + +int drm_fence_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)); + 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_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); + mutex_unlock(&dev->struct_mutex); + 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, + arg. + flags & + DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS, + 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.type); + break; + default: + return -EINVAL; + } + read_lock_irqsave(&fm->lock, flags); + 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 a6535c8db4614376ce8ecb7d889b92db066a96cc Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Aug 2006 10:44:09 +0200 Subject: Add a fence object class field for future use (For example VSYNC fence objects) --- linux-core/drm_fence.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index fc27c576..cfcda2b2 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -397,6 +397,7 @@ int drm_fence_object_init(drm_device_t * dev, uint32_t type, int emit, write_lock_irqsave(&fm->lock, flags); INIT_LIST_HEAD(&fence->ring); + fence->class = 0; fence->type = type; fence->flush_mask = 0; fence->submitted_flush = 0; @@ -577,6 +578,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) 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); -- cgit v1.2.3 From 4c03030b12bae28dad50d69bd271de632c43ff13 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 25 Aug 2006 18:05:35 +0200 Subject: Checkpoint commit Buffer object code. --- linux-core/drm_fence.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index cfcda2b2..897f84c5 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -252,12 +252,17 @@ static void drm_fence_flush_exe(drm_fence_manager_t * fm, } } +int drm_fence_object_signaled(drm_fence_object_t * fence, uint32_t type) +{ + return ((fence->signaled & type) == type); +} + /* * Make sure old fence objects are signaled before their fence sequences are * wrapped around and reused. */ -static int drm_fence_object_flush(drm_device_t * dev, +int drm_fence_object_flush(drm_device_t * dev, drm_fence_object_t * fence, uint32_t type) { drm_fence_manager_t *fm = &dev->fm; @@ -317,8 +322,8 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence) EXPORT_SYMBOL(drm_fence_flush_old); -static int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, - int lazy, int ignore_signals, uint32_t mask) +int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, + int lazy, int ignore_signals, uint32_t mask) { drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; -- cgit v1.2.3 From 11f51a9a877d1231551e8c6482a6f70daf380cdd Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 1 Sep 2006 15:41:55 +0200 Subject: Bugfixes, Memory allocation optimizations. Buffer manager takedown. --- linux-core/drm_fence.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 897f84c5..b4d13621 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -172,7 +172,7 @@ void drm_fence_usage_deref_locked(drm_device_t * dev, { if (atomic_dec_and_test(&fence->usage)) { drm_fence_unring(dev, &fence->ring); - drm_free(fence, sizeof(*fence), DRM_MEM_FENCE); + kmem_cache_free(dev->fence_object_cache, fence); } } @@ -183,7 +183,7 @@ void drm_fence_usage_deref_unlocked(drm_device_t * dev, mutex_lock(&dev->struct_mutex); if (atomic_read(&fence->usage) == 0) { drm_fence_unring(dev, &fence->ring); - drm_free(fence, sizeof(*fence), DRM_MEM_FENCE); + kmem_cache_free(dev->fence_object_cache, fence); } mutex_unlock(&dev->struct_mutex); } @@ -426,7 +426,7 @@ static int drm_fence_object_create(drm_file_t * priv, uint32_t type, int ret; drm_fence_object_t *fence; - fence = drm_calloc(1, sizeof(*fence), DRM_MEM_FENCE); + fence = kmem_cache_alloc(dev->fence_object_cache, GFP_KERNEL); if (!fence) return -ENOMEM; ret = drm_fence_object_init(dev, type, emit, fence); -- cgit v1.2.3 From a6b8e3eaf49044e135a0b9288192525f301458d5 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 4 Sep 2006 16:57:20 +0200 Subject: Make memory caches global so that they can be used with multiple heads. --- linux-core/drm_fence.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index b4d13621..622cad10 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -172,7 +172,7 @@ void drm_fence_usage_deref_locked(drm_device_t * dev, { if (atomic_dec_and_test(&fence->usage)) { drm_fence_unring(dev, &fence->ring); - kmem_cache_free(dev->fence_object_cache, fence); + kmem_cache_free(drm_cache.fence_object, fence); } } @@ -183,7 +183,7 @@ void drm_fence_usage_deref_unlocked(drm_device_t * dev, mutex_lock(&dev->struct_mutex); if (atomic_read(&fence->usage) == 0) { drm_fence_unring(dev, &fence->ring); - kmem_cache_free(dev->fence_object_cache, fence); + kmem_cache_free(drm_cache.fence_object, fence); } mutex_unlock(&dev->struct_mutex); } @@ -426,7 +426,7 @@ static int drm_fence_object_create(drm_file_t * priv, uint32_t type, int ret; drm_fence_object_t *fence; - fence = kmem_cache_alloc(dev->fence_object_cache, GFP_KERNEL); + fence = kmem_cache_alloc(drm_cache.fence_object, GFP_KERNEL); if (!fence) return -ENOMEM; ret = drm_fence_object_init(dev, type, emit, fence); -- cgit v1.2.3 From 550f51b4bf9920718aab2c611b15de3020537f92 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 4 Sep 2006 21:50:12 +0200 Subject: Buffer object wait IOCTL operation. Remove option to wait for fence / buffers and block signals. --- linux-core/drm_fence.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 622cad10..1deeaaa5 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -567,9 +567,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) ret = drm_fence_object_wait(dev, fence, arg.flags & DRM_FENCE_FLAG_WAIT_LAZY, - arg. - flags & - DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS, + 0, arg.type); break; case drm_fence_emit: -- cgit v1.2.3 From 604215396847a7964fd7d68aa89d4f778b3bf22b Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 5 Sep 2006 18:00:25 +0200 Subject: Fence all unfenced buffers function. --- linux-core/drm_fence.c | 96 +++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 36 deletions(-) (limited to 'linux-core/drm_fence.c') 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; } -- cgit v1.2.3 From 99acb7936660843090ea8a9f22d2d50d9433e0de Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 8 Sep 2006 17:24:38 +0200 Subject: Various bugfixes. --- linux-core/drm_fence.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index fd43d8bc..eaaf7f40 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -111,6 +111,10 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) relevant = type & fence->type; if ((fence->signaled | relevant) != fence->signaled) { fence->signaled |= relevant; +#ifdef BODEBUG + DRM_ERROR("Fence 0x%08lx signaled 0x%08x\n", + fence->base.hash.key, fence->signaled); +#endif fence->submitted_flush |= relevant; wake = 1; } @@ -130,6 +134,10 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) */ if (!(fence->type & ~fence->signaled)) { +#ifdef BODEBUG + DRM_ERROR("Fence completely signaled 0x%08lx\n", + fence->base.hash.key); +#endif fence_list = &fence->ring; for (i = 0; i < driver->no_types; ++i) { if (fm->fence_types[i] == fence_list) @@ -172,6 +180,10 @@ void drm_fence_usage_deref_locked(drm_device_t * dev, { if (atomic_dec_and_test(&fence->usage)) { drm_fence_unring(dev, &fence->ring); +#ifdef BODEBUG + DRM_ERROR("Destroyed a fence object 0x%08lx\n", + fence->base.hash.key); +#endif kmem_cache_free(drm_cache.fence_object, fence); } } @@ -430,6 +442,9 @@ int drm_fence_add_user_object(drm_file_t *priv, drm_fence_object_t *fence, return ret; fence->base.type = drm_fence_type; fence->base.remove = &drm_fence_object_destroy; +#ifdef BODEBUG + DRM_ERROR("Fence 0x%08lx created\n", fence->base.hash.key); +#endif return 0; } EXPORT_SYMBOL(drm_fence_add_user_object); -- cgit v1.2.3 From 191e284709ee792a32124e96e43d5876406b93dc Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 12 Sep 2006 12:01:00 +0200 Subject: More bugfixes. Disable the i915 IRQ turnoff for now since it seems to be causing problems. --- linux-core/drm_fence.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index eaaf7f40..df5db702 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -359,12 +359,11 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, fence_signaled(dev, fence, mask, 1)); if (time_after_eq(jiffies, _end)) break; - } while (ret == -EINTR && ignore_signals); - + } while (ret == -EINTR && ignore_signals); if (time_after_eq(jiffies, _end) && (ret != 0)) ret = -EBUSY; - return ret; - + if (ret) + return ((ret == -EINTR) ? -EAGAIN : ret); } else { int signaled; do { -- cgit v1.2.3 From 861b26578cd5e497fb506ad5952fa62bd03ea201 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 12 Sep 2006 16:28:34 +0200 Subject: Use lazy fence wait when possible even for RW fences. Saves some CPU. Lindent. --- linux-core/drm_fence.c | 77 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 25 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index df5db702..4ee5d2d0 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -112,7 +112,7 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) if ((fence->signaled | relevant) != fence->signaled) { fence->signaled |= relevant; #ifdef BODEBUG - DRM_ERROR("Fence 0x%08lx signaled 0x%08x\n", + DRM_ERROR("Fence 0x%08lx signaled 0x%08x\n", fence->base.hash.key, fence->signaled); #endif fence->submitted_flush |= relevant; @@ -135,7 +135,7 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) if (!(fence->type & ~fence->signaled)) { #ifdef BODEBUG - DRM_ERROR("Fence completely signaled 0x%08lx\n", + DRM_ERROR("Fence completely signaled 0x%08lx\n", fence->base.hash.key); #endif fence_list = &fence->ring; @@ -275,7 +275,7 @@ int drm_fence_object_signaled(drm_fence_object_t * fence, uint32_t type) */ int drm_fence_object_flush(drm_device_t * dev, - drm_fence_object_t * fence, uint32_t type) + drm_fence_object_t * fence, uint32_t type) { drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; @@ -341,6 +341,7 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, drm_fence_driver_t *driver = dev->driver->fence_driver; int ret = 0; unsigned long _end; + int signaled; if (mask & ~fence->type) { DRM_ERROR("Wait trying to extend fence type\n"); @@ -353,25 +354,51 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, _end = jiffies + 3 * DRM_HZ; drm_fence_object_flush(dev, fence, mask); + if (lazy && driver->lazy_capable) { + do { DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, fence_signaled(dev, fence, mask, 1)); if (time_after_eq(jiffies, _end)) break; - } while (ret == -EINTR && ignore_signals); + } while (ret == -EINTR && ignore_signals); if (time_after_eq(jiffies, _end) && (ret != 0)) ret = -EBUSY; - if (ret) + if (ret) return ((ret == -EINTR) ? -EAGAIN : ret); - } else { - int signaled; + + } else if ((fence->class == 0) && (mask & DRM_FENCE_EXE) && + driver->lazy_capable) { + + /* + * We use IRQ wait for EXE fence if available to gain + * CPU in some cases. + */ + do { - signaled = fence_signaled(dev, fence, mask, 1); - } while (!signaled && !time_after_eq(jiffies, _end)); - if (!signaled) - return -EBUSY; + DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, + fence_signaled(dev, fence, DRM_FENCE_EXE, + 1)); + if (time_after_eq(jiffies, _end)) + break; + } while (ret == -EINTR && ignore_signals); + if (time_after_eq(jiffies, _end) && (ret != 0)) + ret = -EBUSY; + if (ret) + return ((ret == -EINTR) ? -EAGAIN : ret); } + + if (fence_signaled(dev, fence, mask, 0)) + return 0; + + do { + signaled = fence_signaled(dev, fence, mask, 1); + } while (!signaled && !time_after_eq(jiffies, _end)); + + if (!signaled) + return -EBUSY; + return 0; } @@ -413,7 +440,7 @@ int drm_fence_object_init(drm_device_t * dev, uint32_t type, int emit, write_lock_irqsave(&fm->lock, flags); INIT_LIST_HEAD(&fence->ring); - fence->class = 0; + fence->class = 0; fence->type = type; fence->flush_mask = 0; fence->submitted_flush = 0; @@ -428,7 +455,7 @@ int drm_fence_object_init(drm_device_t * dev, uint32_t type, int emit, EXPORT_SYMBOL(drm_fence_object_init); -int drm_fence_add_user_object(drm_file_t *priv, drm_fence_object_t *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; @@ -446,10 +473,11 @@ int drm_fence_add_user_object(drm_file_t *priv, drm_fence_object_t *fence, #endif 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) +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; @@ -462,11 +490,11 @@ int drm_fence_object_create(drm_device_t *dev, uint32_t type, drm_fence_usage_deref_unlocked(dev, fence); return ret; } - *c_fence = fence; + *c_fence = fence; return 0; } -EXPORT_SYMBOL(drm_fence_object_create); +EXPORT_SYMBOL(drm_fence_object_create); void drm_fence_manager_init(drm_device_t * dev) { @@ -535,8 +563,8 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) &fence); if (ret) return ret; - ret = drm_fence_add_user_object(priv, fence, - arg.flags & + ret = drm_fence_add_user_object(priv, fence, + arg.flags & DRM_FENCE_FLAG_SHAREABLE); if (ret) { drm_fence_usage_deref_unlocked(dev, fence); @@ -588,8 +616,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) ret = drm_fence_object_wait(dev, fence, arg.flags & DRM_FENCE_FLAG_WAIT_LAZY, - 0, - arg.type); + 0, arg.type); break; case drm_fence_emit: LOCK_TEST_WITH_RETURN(dev, filp); @@ -605,16 +632,16 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) } LOCK_TEST_WITH_RETURN(dev, filp); ret = drm_fence_buffer_objects(priv, NULL, NULL, &fence); - if (ret) + if (ret) return ret; - ret = drm_fence_add_user_object(priv, fence, - arg.flags & + 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; + break; default: return -EINVAL; } -- cgit v1.2.3 From 9adc9584a7e0b61b16a943720bef31a71faeaef4 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 12 Sep 2006 17:39:44 +0200 Subject: Fix some debug messages. --- linux-core/drm_fence.c | 16 ++++------------ 1 file changed, 4 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 4ee5d2d0..9ade8114 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -111,10 +111,8 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) relevant = type & fence->type; if ((fence->signaled | relevant) != fence->signaled) { fence->signaled |= relevant; -#ifdef BODEBUG - DRM_ERROR("Fence 0x%08lx signaled 0x%08x\n", + DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n", fence->base.hash.key, fence->signaled); -#endif fence->submitted_flush |= relevant; wake = 1; } @@ -134,10 +132,8 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) */ if (!(fence->type & ~fence->signaled)) { -#ifdef BODEBUG - DRM_ERROR("Fence completely signaled 0x%08lx\n", + DRM_DEBUG("Fence completely signaled 0x%08lx\n", fence->base.hash.key); -#endif fence_list = &fence->ring; for (i = 0; i < driver->no_types; ++i) { if (fm->fence_types[i] == fence_list) @@ -180,10 +176,8 @@ void drm_fence_usage_deref_locked(drm_device_t * dev, { if (atomic_dec_and_test(&fence->usage)) { drm_fence_unring(dev, &fence->ring); -#ifdef BODEBUG - DRM_ERROR("Destroyed a fence object 0x%08lx\n", + DRM_DEBUG("Destroyed a fence object 0x%08lx\n", fence->base.hash.key); -#endif kmem_cache_free(drm_cache.fence_object, fence); } } @@ -468,9 +462,7 @@ int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence, return ret; fence->base.type = drm_fence_type; fence->base.remove = &drm_fence_object_destroy; -#ifdef BODEBUG - DRM_ERROR("Fence 0x%08lx created\n", fence->base.hash.key); -#endif + DRM_DEBUG("Fence 0x%08lx created\n", fence->base.hash.key); return 0; } -- cgit v1.2.3 From 49fbeb339c232804866cd548d6023fe559597353 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 15 Sep 2006 11:18:35 +0200 Subject: Some bugfixes. Change the fence object interface somewhat to allow some more flexibility. Make list IOCTLS really restartable. Try to avoid busy-waits in the kernel using immediate return to user-space with an -EAGAIN. --- linux-core/drm_fence.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 9ade8114..5078e952 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -283,10 +283,10 @@ int drm_fence_object_flush(drm_device_t * dev, write_lock_irqsave(&fm->lock, flags); fence->flush_mask |= type; if (fence->submitted_flush == fence->signaled) { - if ((fence->type & DRM_FENCE_EXE) && - !(fence->submitted_flush & DRM_FENCE_EXE)) { + if ((fence->type & DRM_FENCE_TYPE_EXE) && + !(fence->submitted_flush & DRM_FENCE_TYPE_EXE)) { drm_fence_flush_exe(fm, driver, fence->sequence); - fence->submitted_flush |= DRM_FENCE_EXE; + fence->submitted_flush |= DRM_FENCE_TYPE_EXE; } else { fm->pending_flush |= (fence->flush_mask & ~fence->submitted_flush); @@ -362,7 +362,7 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, if (ret) return ((ret == -EINTR) ? -EAGAIN : ret); - } else if ((fence->class == 0) && (mask & DRM_FENCE_EXE) && + } else if ((fence->class == 0) && (mask & DRM_FENCE_TYPE_EXE) && driver->lazy_capable) { /* @@ -372,7 +372,7 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, do { DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, - fence_signaled(dev, fence, DRM_FENCE_EXE, + fence_signaled(dev, fence, DRM_FENCE_TYPE_EXE, 1)); if (time_after_eq(jiffies, _end)) break; @@ -386,7 +386,15 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, if (fence_signaled(dev, fence, mask, 0)) return 0; - do { + /* + * Avoid kernel-space busy-waits. + */ +#if 1 + if (!ignore_signals) + return -EAGAIN; +#endif + do { + schedule(); signaled = fence_signaled(dev, fence, mask, 1); } while (!signaled && !time_after_eq(jiffies, _end)); -- cgit v1.2.3 From f613022ceef1814cb734bb3375f01962fd3bcf10 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 15 Sep 2006 16:47:09 +0200 Subject: Allow a "native type" to be associated with a fence sequence. In the intel case, we can associate a flush with a sequence. --- linux-core/drm_fence.c | 128 ++++++++++++------------------------------------- 1 file changed, 31 insertions(+), 97 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 5078e952..5d051d4a 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -31,84 +31,35 @@ #include "drmP.h" -static void drm_fm_update_pointers(drm_fence_manager_t * fm, - struct list_head *list, int no_types, - uint32_t type) -{ - int i; - for (i = 0; i < no_types; ++i) { - if (type & (1 << i)) { - fm->fence_types[i] = list; - } - } -} - /* * Typically called by the IRQ handler. */ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) { - int i; int wake = 0; - int largest = 0; uint32_t diff; uint32_t relevant; - int index = 0; drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; - struct list_head *list; - struct list_head *fence_list; + struct list_head *list, *prev; drm_fence_object_t *fence; - int found = 0; - - for (i = 0; i < driver->no_types; ++i) { - if (!(type & (1 << i))) - continue; - - list = fm->fence_types[i]; - fence_list = list->next; - - if (fence_list == &fm->ring) - continue; - - fence = list_entry(fence_list, drm_fence_object_t, ring); + list_for_each_entry(fence, &fm->ring, ring) { diff = (sequence - fence->sequence) & driver->sequence_mask; - - if (diff < driver->wrap_diff) { - if (diff >= largest) { - largest = diff; - index = i; - found = 1; - } - } + if (diff > driver->wrap_diff) + break; } - if (!found) - return; + list = fence->ring.prev; + prev = list->prev; - /* - * Start with the fence object with the lowest sequence number, affected by - * the type mask of this call. Update signaled fields, - * Check if we need to wake sleeping processes - */ - - list = fm->fence_types[index]->next; - do { - if (list == &fm->ring) { - drm_fm_update_pointers(fm, list->prev, - driver->no_types, type); - break; - } + for (; list != &fm->ring; list = prev, prev = list->prev) { fence = list_entry(list, drm_fence_object_t, ring); - diff = (sequence - fence->sequence) & driver->sequence_mask; - if (diff >= driver->wrap_diff) { - drm_fm_update_pointers(fm, fence->ring.prev, - driver->no_types, type); - break; - } + + type |= fence->native_type; relevant = type & fence->type; + if ((fence->signaled | relevant) != fence->signaled) { fence->signaled |= relevant; DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n", @@ -119,35 +70,20 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) relevant = fence->flush_mask & ~(fence->signaled | fence->submitted_flush); + if (relevant) { fm->pending_flush |= relevant; fence->submitted_flush = fence->flush_mask; } - list = list->next; - - /* - * Remove a completely signaled fence from the - * fence manager ring. - */ - if (!(fence->type & ~fence->signaled)) { DRM_DEBUG("Fence completely signaled 0x%08lx\n", fence->base.hash.key); - fence_list = &fence->ring; - for (i = 0; i < driver->no_types; ++i) { - if (fm->fence_types[i] == fence_list) - fm->fence_types[i] = fence_list->prev; - } - list_del_init(fence_list); + list_del_init(&fence->ring); } - } while (1); - - /* - * Wake sleeping processes. - */ - + } + if (wake) { DRM_WAKEUP(&fm->fence_queue); } @@ -158,15 +94,9 @@ EXPORT_SYMBOL(drm_fence_handler); static void drm_fence_unring(drm_device_t * dev, struct list_head *ring) { drm_fence_manager_t *fm = &dev->fm; - drm_fence_driver_t *driver = dev->driver->fence_driver; unsigned long flags; - int i; write_lock_irqsave(&fm->lock, flags); - for (i = 0; i < driver->no_types; ++i) { - if (fm->fence_types[i] == ring) - fm->fence_types[i] = ring->prev; - } list_del_init(ring); write_unlock_irqrestore(&fm->lock, flags); } @@ -235,7 +165,8 @@ static void drm_fence_flush_exe(drm_fence_manager_t * fm, * Last_exe_flush is invalid. Find oldest sequence. */ - list = fm->fence_types[_DRM_FENCE_TYPE_EXE]; +/* list = fm->fence_types[_DRM_FENCE_TYPE_EXE];*/ + list = &fm->ring; if (list->next == &fm->ring) { return; } else { @@ -405,16 +336,17 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, } int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence, - uint32_t type) + uint32_t fence_flags, uint32_t type) { drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; unsigned long flags; uint32_t sequence; + uint32_t native_type; int ret; drm_fence_unring(dev, &fence->ring); - ret = driver->emit(dev, &sequence); + ret = driver->emit(dev, fence_flags, &sequence, &native_type); if (ret) return ret; @@ -424,13 +356,15 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence, fence->submitted_flush = 0x00; fence->signaled = 0x00; fence->sequence = sequence; + fence->native_type = native_type; list_add_tail(&fence->ring, &fm->ring); write_unlock_irqrestore(&fm->lock, flags); return 0; } -int drm_fence_object_init(drm_device_t * dev, uint32_t type, int emit, - drm_fence_object_t * fence) +static int drm_fence_object_init(drm_device_t * dev, uint32_t type, + uint32_t fence_flags, + drm_fence_object_t * fence) { int ret = 0; unsigned long flags; @@ -449,13 +383,12 @@ int drm_fence_object_init(drm_device_t * dev, uint32_t type, int emit, fence->signaled = 0; fence->sequence = 0; write_unlock_irqrestore(&fm->lock, flags); - if (emit) { - ret = drm_fence_object_emit(dev, fence, type); + if (fence_flags & DRM_FENCE_FLAG_EMIT) { + ret = drm_fence_object_emit(dev, fence, fence_flags, type); } return ret; } -EXPORT_SYMBOL(drm_fence_object_init); int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence, int shareable) @@ -477,7 +410,7 @@ int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence, 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) + unsigned flags, drm_fence_object_t ** c_fence) { drm_fence_object_t *fence; int ret; @@ -485,7 +418,7 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t type, fence = kmem_cache_alloc(drm_cache.fence_object, GFP_KERNEL); if (!fence) return -ENOMEM; - ret = drm_fence_object_init(dev, type, emit, fence); + ret = drm_fence_object_init(dev, type, flags, fence); if (ret) { drm_fence_usage_deref_unlocked(dev, fence); return ret; @@ -559,7 +492,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) 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, + arg.flags, &fence); if (ret) return ret; @@ -623,7 +556,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.type); + ret = drm_fence_object_emit(dev, fence, arg.flags, arg.type); break; case drm_fence_buffers: if (!dev->bm.initialized) { @@ -631,7 +564,8 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) return -EINVAL; } LOCK_TEST_WITH_RETURN(dev, filp); - ret = drm_fence_buffer_objects(priv, NULL, NULL, &fence); + ret = drm_fence_buffer_objects(priv, NULL, arg.flags, + NULL, &fence); if (ret) return ret; ret = drm_fence_add_user_object(priv, fence, -- cgit v1.2.3 From c4fad4c96168a3dfabaa8a7e97758fefd014c8a7 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 18 Sep 2006 16:02:33 +0200 Subject: More verbose error reporting in some cases. Add a buffer object waitIdle user-space function. Fix some names and minor glitches. --- linux-core/drm_fence.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 5d051d4a..41fe62a8 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -207,7 +207,8 @@ int drm_fence_object_flush(drm_device_t * dev, unsigned long flags; if (type & ~fence->type) { - DRM_ERROR("Flush trying to extend fence type\n"); + DRM_ERROR("Flush trying to extend fence type, " + "0x%x, 0x%x\n", type, fence->type); return -EINVAL; } @@ -269,7 +270,8 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, int signaled; if (mask & ~fence->type) { - DRM_ERROR("Wait trying to extend fence type\n"); + DRM_ERROR("Wait trying to extend fence type" + " 0x%08x 0x%08x\n", mask, fence->type); return -EINVAL; } -- cgit v1.2.3 From aac918e7c72a46a1b0f2329380e2d6b4196d04e4 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 18 Sep 2006 21:50:00 +0200 Subject: Fence handler fix --- linux-core/drm_fence.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 41fe62a8..cb7aee09 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -31,6 +31,7 @@ #include "drmP.h" + /* * Typically called by the IRQ handler. */ @@ -44,14 +45,20 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) drm_fence_driver_t *driver = dev->driver->fence_driver; struct list_head *list, *prev; drm_fence_object_t *fence; + int found = 0; + + if (list_empty(&fm->ring)) + return; list_for_each_entry(fence, &fm->ring, ring) { diff = (sequence - fence->sequence) & driver->sequence_mask; - if (diff > driver->wrap_diff) + if (diff > driver->wrap_diff) { + found = 1; break; + } } - list = fence->ring.prev; + list = (found) ? fence->ring.prev : fm->ring.prev; prev = list->prev; for (; list != &fm->ring; list = prev, prev = list->prev) { -- cgit v1.2.3 From a02155a0d92d3933d42a3655db261446bfe72b44 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 22 Sep 2006 09:25:36 +0200 Subject: Fix proc formatting broken by last commit. GPU lockup error reporting. --- linux-core/drm_fence.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index cb7aee09..0640e755 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -299,9 +299,12 @@ int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, } while (ret == -EINTR && ignore_signals); if (time_after_eq(jiffies, _end) && (ret != 0)) ret = -EBUSY; - if (ret) + if (ret) { + if (ret == -EBUSY) { + DRM_ERROR("Fence timout. GPU lockup.\n"); + } return ((ret == -EINTR) ? -EAGAIN : ret); - + } } else if ((fence->class == 0) && (mask & DRM_FENCE_TYPE_EXE) && driver->lazy_capable) { -- cgit v1.2.3 From 273eb7833d69db2d72430d5c96c21cebd05c206e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 25 Sep 2006 11:51:08 +0200 Subject: Add /proc filesystem buffer / fence object accounting. Check for NULL pointer in the i915 flush handler. Remove i915_sync_flush declaration. --- linux-core/drm_fence.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 0640e755..ca6c8576 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -111,10 +111,13 @@ static void drm_fence_unring(drm_device_t * dev, struct list_head *ring) void drm_fence_usage_deref_locked(drm_device_t * dev, drm_fence_object_t * fence) { + drm_fence_manager_t *fm = &dev->fm; + 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); kmem_cache_free(drm_cache.fence_object, fence); } } @@ -122,10 +125,13 @@ void drm_fence_usage_deref_locked(drm_device_t * dev, void drm_fence_usage_deref_unlocked(drm_device_t * dev, drm_fence_object_t * fence) { + drm_fence_manager_t *fm = &dev->fm; + if (atomic_dec_and_test(&fence->usage)) { mutex_lock(&dev->struct_mutex); if (atomic_read(&fence->usage) == 0) { drm_fence_unring(dev, &fence->ring); + atomic_dec(&fm->count); kmem_cache_free(drm_cache.fence_object, fence); } mutex_unlock(&dev->struct_mutex); @@ -142,7 +148,8 @@ 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, drm_fence_object_t * fence, +static int fence_signaled(drm_device_t * dev, volatile + drm_fence_object_t * fence, uint32_t mask, int poke_flush) { unsigned long flags; @@ -166,7 +173,7 @@ static void drm_fence_flush_exe(drm_fence_manager_t * fm, uint32_t diff; if (!fm->pending_exe_flush) { - struct list_head *list; + volatile struct list_head *list; /* * Last_exe_flush is invalid. Find oldest sequence. @@ -196,18 +203,15 @@ static void drm_fence_flush_exe(drm_fence_manager_t * fm, } } -int drm_fence_object_signaled(drm_fence_object_t * fence, uint32_t type) +int drm_fence_object_signaled(volatile drm_fence_object_t * fence, + uint32_t type) { return ((fence->signaled & type) == type); } -/* - * Make sure old fence objects are signaled before their fence sequences are - * wrapped around and reused. - */ - int drm_fence_object_flush(drm_device_t * dev, - drm_fence_object_t * fence, uint32_t type) + volatile drm_fence_object_t * fence, + uint32_t type) { drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; @@ -237,6 +241,12 @@ int drm_fence_object_flush(drm_device_t * dev, return 0; } +/* + * Make sure old fence objects are signaled before their fence sequences are + * wrapped around and reused. + */ + + void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence) { drm_fence_manager_t *fm = &dev->fm; @@ -267,7 +277,8 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence) EXPORT_SYMBOL(drm_fence_flush_old); -int drm_fence_object_wait(drm_device_t * dev, drm_fence_object_t * fence, +int drm_fence_object_wait(drm_device_t * dev, + volatile drm_fence_object_t * fence, int lazy, int ignore_signals, uint32_t mask) { drm_fence_manager_t *fm = &dev->fm; @@ -426,6 +437,8 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t type, { drm_fence_object_t *fence; int ret; + drm_fence_manager_t *fm = &dev->fm; + unsigned long fl; fence = kmem_cache_alloc(drm_cache.fence_object, GFP_KERNEL); if (!fence) @@ -436,6 +449,8 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t type, return ret; } *c_fence = fence; + atomic_inc(&fm->count); + return 0; } @@ -448,16 +463,19 @@ void drm_fence_manager_init(drm_device_t * dev) int i; fm->lock = RW_LOCK_UNLOCKED; + write_lock(&fm->lock); INIT_LIST_HEAD(&fm->ring); fm->pending_flush = 0; DRM_INIT_WAITQUEUE(&fm->fence_queue); fm->initialized = 0; if (fed) { fm->initialized = 1; + atomic_set(&fm->count,0); for (i = 0; i < fed->no_types; ++i) { fm->fence_types[i] = &fm->ring; } } + write_unlock(&fm->lock); } void drm_fence_manager_takedown(drm_device_t * dev) -- cgit v1.2.3 From 711f077b7423c1a436d703885c6d18a2ad2940aa Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 26 Sep 2006 14:36:53 +0200 Subject: Allow for a driver to overload the ttm backend object methods. --- linux-core/drm_fence.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index ca6c8576..3e20f129 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -438,7 +438,6 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t type, drm_fence_object_t *fence; int ret; drm_fence_manager_t *fm = &dev->fm; - unsigned long fl; fence = kmem_cache_alloc(drm_cache.fence_object, GFP_KERNEL); if (!fence) -- cgit v1.2.3 From d515936ea7f98f6aaa9217699796beadef9d664b Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 17 Oct 2006 19:40:57 +0200 Subject: Add memory usage accounting to avoid DOS problems. --- linux-core/drm_fence.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 3e20f129..c9a2a062 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -118,7 +118,8 @@ void drm_fence_usage_deref_locked(drm_device_t * dev, DRM_DEBUG("Destroyed a fence object 0x%08lx\n", fence->base.hash.key); atomic_dec(&fm->count); - kmem_cache_free(drm_cache.fence_object, fence); + drm_ctl_cache_free(drm_cache.fence_object, sizeof(*fence), + fence); } } @@ -132,7 +133,8 @@ 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); - kmem_cache_free(drm_cache.fence_object, fence); + drm_ctl_cache_free(drm_cache.fence_object, + sizeof(*fence), fence); } mutex_unlock(&dev->struct_mutex); } @@ -439,7 +441,8 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t type, int ret; drm_fence_manager_t *fm = &dev->fm; - fence = kmem_cache_alloc(drm_cache.fence_object, GFP_KERNEL); + fence = drm_ctl_cache_alloc(drm_cache.fence_object, + sizeof(*fence), GFP_KERNEL); if (!fence) return -ENOMEM; ret = drm_fence_object_init(dev, type, flags, fence); -- cgit v1.2.3 From 89b944179856fadf8667587eff142129c2c6b826 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 17 Oct 2006 19:57:06 +0200 Subject: Lindent. --- linux-core/drm_fence.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index c9a2a062..aa382046 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -31,7 +31,6 @@ #include "drmP.h" - /* * Typically called by the IRQ handler. */ @@ -90,7 +89,7 @@ void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) } } - + if (wake) { DRM_WAKEUP(&fm->fence_queue); } @@ -132,8 +131,8 @@ void drm_fence_usage_deref_unlocked(drm_device_t * dev, mutex_lock(&dev->struct_mutex); if (atomic_read(&fence->usage) == 0) { drm_fence_unring(dev, &fence->ring); - atomic_dec(&fm->count); - drm_ctl_cache_free(drm_cache.fence_object, + atomic_dec(&fm->count); + drm_ctl_cache_free(drm_cache.fence_object, sizeof(*fence), fence); } mutex_unlock(&dev->struct_mutex); @@ -150,7 +149,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, volatile +static int fence_signaled(drm_device_t * dev, volatile drm_fence_object_t * fence, uint32_t mask, int poke_flush) { @@ -205,15 +204,14 @@ static void drm_fence_flush_exe(drm_fence_manager_t * fm, } } -int drm_fence_object_signaled(volatile drm_fence_object_t * fence, +int drm_fence_object_signaled(volatile drm_fence_object_t * fence, uint32_t type) { return ((fence->signaled & type) == type); } int drm_fence_object_flush(drm_device_t * dev, - volatile drm_fence_object_t * fence, - uint32_t type) + volatile drm_fence_object_t * fence, uint32_t type) { drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; @@ -221,7 +219,7 @@ int drm_fence_object_flush(drm_device_t * dev, if (type & ~fence->type) { DRM_ERROR("Flush trying to extend fence type, " - "0x%x, 0x%x\n", type, fence->type); + "0x%x, 0x%x\n", type, fence->type); return -EINVAL; } @@ -248,7 +246,6 @@ int drm_fence_object_flush(drm_device_t * dev, * wrapped around and reused. */ - void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence) { drm_fence_manager_t *fm = &dev->fm; @@ -279,7 +276,7 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence) EXPORT_SYMBOL(drm_fence_flush_old); -int drm_fence_object_wait(drm_device_t * dev, +int drm_fence_object_wait(drm_device_t * dev, volatile drm_fence_object_t * fence, int lazy, int ignore_signals, uint32_t mask) { @@ -328,8 +325,8 @@ int drm_fence_object_wait(drm_device_t * dev, do { DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, - fence_signaled(dev, fence, DRM_FENCE_TYPE_EXE, - 1)); + fence_signaled(dev, fence, + DRM_FENCE_TYPE_EXE, 1)); if (time_after_eq(jiffies, _end)) break; } while (ret == -EINTR && ignore_signals); @@ -347,9 +344,9 @@ int drm_fence_object_wait(drm_device_t * dev, */ #if 1 if (!ignore_signals) - return -EAGAIN; + return -EAGAIN; #endif - do { + do { schedule(); signaled = fence_signaled(dev, fence, mask, 1); } while (!signaled && !time_after_eq(jiffies, _end)); @@ -387,7 +384,7 @@ 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 type, +static int drm_fence_object_init(drm_device_t * dev, uint32_t type, uint32_t fence_flags, drm_fence_object_t * fence) { @@ -414,7 +411,6 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t type, return ret; } - int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence, int shareable) { @@ -441,7 +437,7 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t type, int ret; drm_fence_manager_t *fm = &dev->fm; - fence = drm_ctl_cache_alloc(drm_cache.fence_object, + fence = drm_ctl_cache_alloc(drm_cache.fence_object, sizeof(*fence), GFP_KERNEL); if (!fence) return -ENOMEM; @@ -472,7 +468,7 @@ void drm_fence_manager_init(drm_device_t * dev) fm->initialized = 0; if (fed) { fm->initialized = 1; - atomic_set(&fm->count,0); + atomic_set(&fm->count, 0); for (i = 0; i < fed->no_types; ++i) { fm->fence_types[i] = &fm->ring; } @@ -523,9 +519,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) 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, - &fence); + ret = drm_fence_object_create(dev, arg.type, arg.flags, &fence); if (ret) return ret; ret = drm_fence_add_user_object(priv, fence, @@ -596,7 +590,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS) return -EINVAL; } LOCK_TEST_WITH_RETURN(dev, filp); - ret = drm_fence_buffer_objects(priv, NULL, arg.flags, + ret = drm_fence_buffer_objects(priv, NULL, arg.flags, NULL, &fence); if (ret) return ret; -- cgit v1.2.3 From e8ba62db722eb0b915377269d7e1c3a039928669 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 19 Oct 2006 16:58:00 +0200 Subject: Make sure delayed delete list is empty on lastclose. Fix some refcounting errors. Fix some error messages. --- linux-core/drm_fence.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_fence.c') diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index aa382046..f656340e 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -311,7 +311,9 @@ int drm_fence_object_wait(drm_device_t * dev, ret = -EBUSY; if (ret) { if (ret == -EBUSY) { - DRM_ERROR("Fence timout. GPU lockup.\n"); + DRM_ERROR("Fence timeout. " + "GPU lockup or fence driver was " + "taken down.\n"); } return ((ret == -EINTR) ? -EAGAIN : ret); } -- cgit v1.2.3