Initial support for fence object classes.
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Thu, 15 Feb 2007 11:10:33 +0000 (12:10 +0100)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Thu, 15 Feb 2007 11:11:38 +0000 (12:11 +0100)
(Fence objects belonging to different command submission mechanisms).

libdrm/xf86drm.c
linux-core/drm_bo.c
linux-core/drm_bo_move.c
linux-core/drm_fence.c
linux-core/drm_objects.h
linux-core/i915_buffer.c
linux-core/i915_drv.c
linux-core/i915_fence.c
shared-core/i915_dma.c

index 56450e8..1a8edee 100644 (file)
@@ -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;
index e593258..8fc2a30 100644 (file)
@@ -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);
index 21f5f6c..4f75206 100644 (file)
@@ -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)
index 3ccfdcb..634cf4f 100644 (file)
@@ -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; i<fm->num_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) {
index f9b8ebd..547de6b 100644 (file)
@@ -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);
index 374b28d..2cb0dc5 100644 (file)
@@ -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);
index b7bf883..33daf48 100644 (file)
@@ -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,
index fa2a3d1..81d9b17 100644 (file)
@@ -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) {
index 9624fac..98a3b7c 100644 (file)
@@ -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;