From 7766378d97323de375687285f2e125008b79045d Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 15 Feb 2007 12:10:33 +0100 Subject: Initial support for fence object classes. (Fence objects belonging to different command submission mechanisms). --- libdrm/xf86drm.c | 5 ++- linux-core/drm_bo.c | 2 +- linux-core/drm_bo_move.c | 3 +- linux-core/drm_fence.c | 101 ++++++++++++++++++++++++++++------------------- linux-core/drm_objects.h | 29 +++++++------- linux-core/i915_buffer.c | 2 +- linux-core/i915_drv.c | 2 +- linux-core/i915_fence.c | 15 +++---- shared-core/i915_dma.c | 4 +- 9 files changed, 93 insertions(+), 70 deletions(-) diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index 56450e80..1a8edeef 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -2267,7 +2267,7 @@ int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data, * DRM_FENCE_MASK_DRIVER */ -int drmFenceCreate(int fd, unsigned flags, int class,unsigned type, +int drmFenceCreate(int fd, unsigned flags, int class, unsigned type, drmFence *fence) { drm_fence_arg_t arg; @@ -2410,8 +2410,9 @@ int drmFenceSignaled(int fd, drmFence *fence, unsigned fenceType, int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type) { drm_fence_arg_t arg; - + memset(&arg, 0, sizeof(arg)); + arg.class = fence->class; arg.flags = flags; arg.handle = fence->handle; arg.type = emit_type; diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index e593258b..8fc2a30e 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -561,7 +561,7 @@ int drm_fence_buffer_objects(drm_file_t * priv, } } else { mutex_unlock(&dev->struct_mutex); - ret = drm_fence_object_create(dev, fence_type, + ret = drm_fence_object_create(dev, 0, fence_type, fence_flags | DRM_FENCE_FLAG_EMIT, &fence); mutex_lock(&dev->struct_mutex); diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index 21f5f6cc..4f752065 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -326,6 +326,7 @@ int drm_buffer_object_transfer(drm_buffer_object_t * bo, int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo, int evict, int no_wait, + uint32_t fence_class, uint32_t fence_type, uint32_t fence_flags, drm_bo_mem_reg_t * new_mem) { @@ -339,7 +340,7 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo, if (bo->fence) drm_fence_usage_deref_unlocked(dev, bo->fence); - ret = drm_fence_object_create(dev, fence_type, + ret = drm_fence_object_create(dev, fence_class, fence_type, fence_flags | DRM_FENCE_FLAG_EMIT, &bo->fence); if (ret) diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 3ccfdcb8..634cf4f7 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -41,15 +41,16 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class, uint32_t diff; uint32_t relevant; drm_fence_manager_t *fm = &dev->fm; + drm_fence_class_manager_t *fc = &fm->class[class]; drm_fence_driver_t *driver = dev->driver->fence_driver; struct list_head *list, *prev; drm_fence_object_t *fence; int found = 0; - if (list_empty(&fm->ring)) + if (list_empty(&fc->ring)) return; - list_for_each_entry(fence, &fm->ring, ring) { + list_for_each_entry(fence, &fc->ring, ring) { diff = (sequence - fence->sequence) & driver->sequence_mask; if (diff > driver->wrap_diff) { found = 1; @@ -57,10 +58,10 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class, } } - list = (found) ? fence->ring.prev : fm->ring.prev; + list = (found) ? fence->ring.prev : fc->ring.prev; prev = list->prev; - for (; list != &fm->ring; list = prev, prev = list->prev) { + for (; list != &fc->ring; list = prev, prev = list->prev) { fence = list_entry(list, drm_fence_object_t, ring); type |= fence->native_type; @@ -78,7 +79,7 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class, ~(fence->signaled | fence->submitted_flush); if (relevant) { - fm->pending_flush |= relevant; + fc->pending_flush |= relevant; fence->submitted_flush = fence->flush_mask; } @@ -91,7 +92,7 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class, } if (wake) { - DRM_WAKEUP(&fm->fence_queue); + DRM_WAKEUP(&fc->fence_queue); } } @@ -166,37 +167,37 @@ static int fence_signaled(drm_device_t * dev, return signaled; } -static void drm_fence_flush_exe(drm_fence_manager_t * fm, +static void drm_fence_flush_exe(drm_fence_class_manager_t * fc, drm_fence_driver_t * driver, uint32_t sequence) { uint32_t diff; - if (!fm->pending_exe_flush) { + if (!fc->pending_exe_flush) { struct list_head *list; /* * Last_exe_flush is invalid. Find oldest sequence. */ - list = &fm->ring; - if (list->next == &fm->ring) { + list = &fc->ring; + if (list->next == &fc->ring) { return; } else { drm_fence_object_t *fence = list_entry(list->next, drm_fence_object_t, ring); - fm->last_exe_flush = (fence->sequence - 1) & + fc->last_exe_flush = (fence->sequence - 1) & driver->sequence_mask; } - diff = (sequence - fm->last_exe_flush) & driver->sequence_mask; + diff = (sequence - fc->last_exe_flush) & driver->sequence_mask; if (diff >= driver->wrap_diff) return; - fm->exe_flush_sequence = sequence; - fm->pending_exe_flush = 1; + fc->exe_flush_sequence = sequence; + fc->pending_exe_flush = 1; } else { diff = - (sequence - fm->exe_flush_sequence) & driver->sequence_mask; + (sequence - fc->exe_flush_sequence) & driver->sequence_mask; if (diff < driver->wrap_diff) { - fm->exe_flush_sequence = sequence; + fc->exe_flush_sequence = sequence; } } } @@ -212,6 +213,7 @@ int drm_fence_object_flush(drm_device_t * dev, uint32_t type) { drm_fence_manager_t *fm = &dev->fm; + drm_fence_class_manager_t *fc = &fm->class[fence->class]; drm_fence_driver_t *driver = dev->driver->fence_driver; unsigned long flags; @@ -226,10 +228,10 @@ int drm_fence_object_flush(drm_device_t * dev, if (fence->submitted_flush == fence->signaled) { if ((fence->type & DRM_FENCE_TYPE_EXE) && !(fence->submitted_flush & DRM_FENCE_TYPE_EXE)) { - drm_fence_flush_exe(fm, driver, fence->sequence); + drm_fence_flush_exe(fc, driver, fence->sequence); fence->submitted_flush |= DRM_FENCE_TYPE_EXE; } else { - fm->pending_flush |= (fence->flush_mask & + fc->pending_flush |= (fence->flush_mask & ~fence->submitted_flush); fence->submitted_flush = fence->flush_mask; } @@ -244,9 +246,10 @@ 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) +void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence) { drm_fence_manager_t *fm = &dev->fm; + drm_fence_class_manager_t *fc = &fm->class[class]; drm_fence_driver_t *driver = dev->driver->fence_driver; uint32_t old_sequence; unsigned long flags; @@ -255,13 +258,13 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence) mutex_lock(&dev->struct_mutex); read_lock_irqsave(&fm->lock, flags); - if (fm->ring.next == &fm->ring) { + if (fc->ring.next == &fc->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); + fence = list_entry(fc->ring.next, drm_fence_object_t, ring); atomic_inc(&fence->usage); mutex_unlock(&dev->struct_mutex); diff = (old_sequence - fence->sequence) & driver->sequence_mask; @@ -279,11 +282,13 @@ static int drm_fence_lazy_wait(drm_device_t *dev, int ignore_signals, uint32_t mask) { drm_fence_manager_t *fm = &dev->fm; + drm_fence_class_manager_t *fc = &fm->class[fence->class]; + unsigned long _end = jiffies + 3*DRM_HZ; int ret = 0; do { - DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ, fence_signaled(dev, fence, mask, 1)); if (time_after_eq(jiffies, _end)) break; @@ -370,7 +375,7 @@ int drm_fence_object_wait(drm_device_t * dev, } int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence, - uint32_t fence_flags, uint32_t type) + uint32_t fence_flags, uint32_t class, uint32_t type) { drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; @@ -380,23 +385,25 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence, int ret; drm_fence_unring(dev, &fence->ring); - ret = driver->emit(dev, fence->class, fence_flags, &sequence, &native_type); + ret = driver->emit(dev, class, fence_flags, &sequence, &native_type); if (ret) return ret; write_lock_irqsave(&fm->lock, flags); + fence->class = class; fence->type = type; fence->flush_mask = 0x00; fence->submitted_flush = 0x00; fence->signaled = 0x00; fence->sequence = sequence; fence->native_type = native_type; - list_add_tail(&fence->ring, &fm->ring); + list_add_tail(&fence->ring, &fm->class[class].ring); write_unlock_irqrestore(&fm->lock, flags); 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 class, + uint32_t type, uint32_t fence_flags, drm_fence_object_t * fence) { @@ -410,7 +417,7 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t type, write_lock_irqsave(&fm->lock, flags); INIT_LIST_HEAD(&fence->ring); - fence->class = 0; + fence->class = class; fence->type = type; fence->flush_mask = 0; fence->submitted_flush = 0; @@ -418,7 +425,8 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t type, fence->sequence = 0; write_unlock_irqrestore(&fm->lock, flags); if (fence_flags & DRM_FENCE_FLAG_EMIT) { - ret = drm_fence_object_emit(dev, fence, fence_flags, type); + ret = drm_fence_object_emit(dev, fence, fence_flags, + fence->class, type); } return ret; } @@ -442,7 +450,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 drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type, unsigned flags, drm_fence_object_t ** c_fence) { drm_fence_object_t *fence; @@ -452,7 +460,7 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t type, fence = drm_ctl_alloc(sizeof(*fence), DRM_MEM_FENCE); if (!fence) return -ENOMEM; - ret = drm_fence_object_init(dev, type, flags, fence); + ret = drm_fence_object_init(dev, class, type, flags, fence); if (ret) { drm_fence_usage_deref_unlocked(dev, fence); return ret; @@ -468,22 +476,31 @@ EXPORT_SYMBOL(drm_fence_object_create); void drm_fence_manager_init(drm_device_t * dev) { drm_fence_manager_t *fm = &dev->fm; + drm_fence_class_manager_t *class; drm_fence_driver_t *fed = dev->driver->fence_driver; 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; - } + if (!fed) + goto out_unlock; + + fm->initialized = 1; + fm->num_classes = fed->num_classes; + BUG_ON(fm->num_classes > _DRM_FENCE_CLASSES); + + for (i=0; inum_classes; ++i) { + class = &fm->class[i]; + + INIT_LIST_HEAD(&class->ring); + class->pending_flush = 0; + DRM_INIT_WAITQUEUE(&class->fence_queue); } + + atomic_set(&fm->count, 0); + out_unlock: write_unlock(&fm->lock); } @@ -530,7 +547,8 @@ 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.class, + arg.type, arg.flags, &fence); if (ret) return ret; ret = drm_fence_add_user_object(priv, fence, @@ -593,7 +611,8 @@ 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.type); + ret = drm_fence_object_emit(dev, fence, arg.flags, arg.class, + arg.type); break; case drm_fence_buffers: if (!dev->bm.initialized) { diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index f9b8ebd9..547de6b4 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -158,29 +158,28 @@ typedef struct drm_fence_object { uint32_t submitted_flush; } drm_fence_object_t; +#define _DRM_FENCE_CLASSES 8 #define _DRM_FENCE_TYPE_EXE 0x00 -typedef struct drm_fence_manager { - int initialized; - rwlock_t lock; - - /* - * The list below should be maintained in sequence order and - * access is protected by the above spinlock. - */ - +typedef struct drm_fence_class_manager { struct list_head ring; - struct list_head *fence_types[32]; - volatile uint32_t pending_flush; + uint32_t pending_flush; wait_queue_head_t fence_queue; int pending_exe_flush; uint32_t last_exe_flush; uint32_t exe_flush_sequence; +} drm_fence_class_manager_t; + +typedef struct drm_fence_manager { + int initialized; + rwlock_t lock; + drm_fence_class_manager_t class[_DRM_FENCE_CLASSES]; + uint32_t num_classes; atomic_t count; } drm_fence_manager_t; typedef struct drm_fence_driver { - int no_types; + uint32_t num_classes; uint32_t wrap_diff; uint32_t flush_diff; uint32_t sequence_mask; @@ -196,7 +195,8 @@ extern void drm_fence_handler(struct drm_device *dev, uint32_t class, uint32_t sequence, uint32_t type); extern void drm_fence_manager_init(struct drm_device *dev); extern void drm_fence_manager_takedown(struct drm_device *dev); -extern void drm_fence_flush_old(struct drm_device *dev, uint32_t sequence); +extern void drm_fence_flush_old(struct drm_device *dev, uint32_t class, + uint32_t sequence); extern int drm_fence_object_flush(struct drm_device *dev, drm_fence_object_t * fence, uint32_t type); extern int drm_fence_object_signaled(drm_fence_object_t * fence, uint32_t type); @@ -208,7 +208,7 @@ extern int drm_fence_object_wait(struct drm_device *dev, drm_fence_object_t * fence, int lazy, int ignore_signals, uint32_t mask); extern int drm_fence_object_create(struct drm_device *dev, uint32_t type, - uint32_t fence_flags, + uint32_t fence_flags, uint32_t class, drm_fence_object_t ** c_fence); extern int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence, int shareable); @@ -462,6 +462,7 @@ extern int drm_bo_move_memcpy(drm_buffer_object_t * bo, extern int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo, int evict, int no_wait, + uint32_t fence_class, uint32_t fence_type, uint32_t fence_flags, drm_bo_mem_reg_t * new_mem); diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index 374b28df..2cb0dc5f 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -170,7 +170,7 @@ static int i915_move_blit(drm_buffer_object_t * bo, i915_emit_mi_flush(bo->dev, MI_READ_FLUSH | MI_EXE_FLUSH); - return drm_bo_move_accel_cleanup(bo, evict, no_wait, + return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, DRM_I915_FENCE_FLAG_FLUSHED, new_mem); diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index b7bf883c..33daf480 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -40,7 +40,7 @@ static struct pci_device_id pciidlist[] = { #ifdef I915_HAVE_FENCE static drm_fence_driver_t i915_fence_driver = { - .no_types = 2, + .num_classes = 1, .wrap_diff = (1 << 30), .flush_diff = (1 << 29), .sequence_mask = 0xffffffffU, diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c index fa2a3d1f..81d9b176 100644 --- a/linux-core/i915_fence.c +++ b/linux-core/i915_fence.c @@ -42,6 +42,7 @@ static void i915_perform_flush(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_fence_manager_t *fm = &dev->fm; + drm_fence_class_manager_t *fc = &fm->class[0]; drm_fence_driver_t *driver = dev->driver->fence_driver; uint32_t flush_flags = 0; uint32_t flush_sequence = 0; @@ -52,21 +53,21 @@ static void i915_perform_flush(drm_device_t * dev) if (!dev_priv) return; - if (fm->pending_exe_flush) { + if (fc->pending_exe_flush) { sequence = READ_BREADCRUMB(dev_priv); /* * First update fences with the current breadcrumb. */ - diff = sequence - fm->last_exe_flush; + diff = sequence - fc->last_exe_flush; if (diff < driver->wrap_diff && diff != 0) { drm_fence_handler(dev, 0, sequence, DRM_FENCE_TYPE_EXE); } - diff = sequence - fm->exe_flush_sequence; + diff = sequence - fc->exe_flush_sequence; if (diff < driver->wrap_diff) { - fm->pending_exe_flush = 0; + fc->pending_exe_flush = 0; if (dev_priv->fence_irq_on) { i915_user_irq_off(dev_priv); dev_priv->fence_irq_on = 0; @@ -88,13 +89,13 @@ static void i915_perform_flush(drm_device_t * dev) } } - if (fm->pending_flush && !dev_priv->flush_pending) { + if (fc->pending_flush && !dev_priv->flush_pending) { dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv); - dev_priv->flush_flags = fm->pending_flush; + dev_priv->flush_flags = fc->pending_flush; dev_priv->saved_flush_status = READ_HWSP(dev_priv, 0); I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21)); dev_priv->flush_pending = 1; - fm->pending_flush = 0; + fc->pending_flush = 0; } if (dev_priv->flush_pending) { diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 9624fac4..98a3b7c8 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -443,7 +443,7 @@ static void i915_emit_breadcrumb(drm_device_t *dev) OUT_RING(0); ADVANCE_LP_RING(); #ifdef I915_HAVE_FENCE - drm_fence_flush_old(dev, dev_priv->counter); + drm_fence_flush_old(dev, 0, dev_priv->counter); #endif } @@ -590,7 +590,7 @@ static int i915_dispatch_flip(drm_device_t * dev) OUT_RING(0); ADVANCE_LP_RING(); #ifdef I915_HAVE_FENCE - drm_fence_flush_old(dev, dev_priv->counter); + drm_fence_flush_old(dev, 0, dev_priv->counter); #endif dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; return 0; -- cgit v1.2.3