Simple fence object sample driver for via, based on idling the GPU.
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Fri, 16 Feb 2007 19:22:24 +0000 (20:22 +0100)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Fri, 16 Feb 2007 19:22:24 +0000 (20:22 +0100)
Buffer object driver for via.
Some changes to buffer object driver callbacks.
Improve fence flushing.

13 files changed:
libdrm/xf86drm.c
linux-core/Makefile.kernel
linux-core/drm_bo.c
linux-core/drm_fence.c
linux-core/drm_objects.h
linux-core/i915_buffer.c
linux-core/i915_drv.c
shared-core/i915_drv.h
shared-core/via_dma.c
shared-core/via_drm.h
shared-core/via_drv.c
shared-core/via_drv.h
shared-core/via_map.c

index 1a8edee..862772d 100644 (file)
@@ -2271,8 +2271,9 @@ int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
                   drmFence *fence)
 {
     drm_fence_arg_t arg;
-    
+
     memset(&arg, 0, sizeof(arg));
+    arg.flags = flags;
     arg.type = type;
     arg.class = class;
     arg.op = drm_fence_create;
index c2bfb67..08c0fb2 100644 (file)
@@ -29,8 +29,8 @@ sis-objs    := sis_drv.o sis_mm.o
 ffb-objs    := ffb_drv.o ffb_context.o
 savage-objs := savage_drv.o savage_bci.o savage_state.o
 via-objs    := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o \
-               via_video.o via_dmablit.o 
-mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o 
+               via_video.o via_dmablit.o via_fence.o via_buffer.o
+mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
 nv-objs := nv_drv.o
 
 ifeq ($(CONFIG_COMPAT),y)
index 8fc2a30..548ce14 100644 (file)
@@ -641,7 +641,7 @@ static int drm_bo_evict(drm_buffer_object_t * bo, unsigned mem_type,
        }
 
        evict_mem = bo->mem;
-       evict_mem.mask = dev->driver->bo_driver->evict_flags(dev, mem_type);
+       evict_mem.mask = dev->driver->bo_driver->evict_mask(bo);
        ret = drm_bo_mem_space(bo, &evict_mem, no_wait);
 
        if (ret) {
@@ -1351,7 +1351,7 @@ static int drm_buffer_object_validate(drm_buffer_object_t * bo,
        DRM_DEBUG("New flags 0x%08x, Old flags 0x%08x\n", bo->mem.mask,
                  bo->mem.flags);
        ret =
-           driver->fence_type(bo->mem.mask, &bo->fence_class, &bo->fence_type);
+           driver->fence_type(bo, &bo->fence_class, &bo->fence_type);
        if (ret) {
                DRM_ERROR("Driver did not support given buffer permissions\n");
                return ret;
@@ -2001,9 +2001,9 @@ static int drm_bo_lock_mm(drm_device_t * dev, unsigned mem_type)
        return ret;
 }
 
-static int drm_bo_init_mm(drm_device_t * dev,
-                         unsigned type,
-                         unsigned long p_offset, unsigned long p_size)
+int drm_bo_init_mm(drm_device_t * dev,
+                  unsigned type,
+                  unsigned long p_offset, unsigned long p_size)
 {
        drm_buffer_manager_t *bm = &dev->bm;
        int ret = -EINVAL;
@@ -2043,6 +2043,7 @@ static int drm_bo_init_mm(drm_device_t * dev,
 
        return 0;
 }
+EXPORT_SYMBOL(drm_bo_init_mm);
 
 /*
  * This is called from lastclose, so we don't need to bother about
index 634cf4f..3e17a16 100644 (file)
@@ -91,6 +91,11 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
 
        }
 
+       fc->pending_flush &= ~type;
+       if (fc->pending_exe_flush && (type & DRM_FENCE_TYPE_EXE) &&
+           ((sequence - fc->exe_flush_sequence) < driver->wrap_diff))
+               fc->pending_exe_flush = 0;
+
        if (wake) {
                DRM_WAKEUP(&fc->fence_queue);
        }
@@ -180,7 +185,7 @@ static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
                 */
 
                list = &fc->ring;
-               if (list->next == &fc->ring) {
+               if (list_empty(list)) {
                        return;
                } else {
                        drm_fence_object_t *fence =
@@ -279,7 +284,8 @@ EXPORT_SYMBOL(drm_fence_flush_old);
 
 static int drm_fence_lazy_wait(drm_device_t *dev,
                               drm_fence_object_t *fence,
-                              int ignore_signals, uint32_t mask)
+                              int ignore_signals,
+                              uint32_t mask)
 {
        drm_fence_manager_t *fm = &dev->fm;
        drm_fence_class_manager_t *fc = &fm->class[fence->class];
@@ -289,7 +295,7 @@ static int drm_fence_lazy_wait(drm_device_t *dev,
 
        do {
                DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ,
-                           fence_signaled(dev, fence, mask, 1));
+                           fence_signaled(dev, fence, mask, 0));
                if (time_after_eq(jiffies, _end))
                        break;
        } while (ret == -EINTR && ignore_signals);
@@ -352,10 +358,9 @@ int drm_fence_object_wait(drm_device_t * dev,
                                return ret;
                }
        }
-       if (fence_signaled(dev, fence, mask, 0))
+       if (drm_fence_object_signaled(fence, mask))
                return 0;
 
-       DRM_ERROR("Busy wait\n");
        /*
         * Avoid kernel-space busy-waits.
         */
index 547de6b..98228ad 100644 (file)
@@ -411,11 +411,11 @@ typedef struct drm_bo_driver {
        uint32_t num_mem_busy_prio;
        drm_ttm_backend_t *(*create_ttm_backend_entry)
         (struct drm_device * dev);
-       int (*fence_type) (uint32_t flags, uint32_t * class, uint32_t * type);
+       int (*fence_type) (struct drm_buffer_object *bo, uint32_t * class, uint32_t * type);
        int (*invalidate_caches) (struct drm_device * dev, uint32_t flags);
        int (*init_mem_type) (struct drm_device * dev, uint32_t type,
                              drm_mem_type_manager_t * man);
-        uint32_t(*evict_flags) (struct drm_device * dev, uint32_t type);
+        uint32_t(*evict_mask) (struct drm_buffer_object *bo);
        int (*move) (struct drm_buffer_object * bo,
                     int evict, int no_wait, struct drm_bo_mem_reg * new_mem);
 } drm_bo_driver_t;
index 2cb0dc5..8797de8 100644 (file)
@@ -38,10 +38,10 @@ drm_ttm_backend_t *i915_create_ttm_backend_entry(drm_device_t * dev)
        return drm_agp_init_ttm(dev, NULL);
 }
 
-int i915_fence_types(uint32_t buffer_flags, uint32_t * class, uint32_t * type)
+int i915_fence_types(drm_buffer_object_t *bo, uint32_t * class, uint32_t * type)
 {
        *class = 0;
-       if (buffer_flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
+       if (bo->mem.flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
                *type = 3;
        else
                *type = 1;
@@ -106,9 +106,9 @@ int i915_init_mem_type(drm_device_t * dev, uint32_t type,
        return 0;
 }
 
-uint32_t i915_evict_flags(drm_device_t * dev, uint32_t type)
+uint32_t i915_evict_mask(drm_buffer_object_t *bo)
 {
-       switch (type) {
+       switch (bo->mem.mem_type) {
        case DRM_BO_MEM_LOCAL:
        case DRM_BO_MEM_TT:
                return DRM_BO_FLAG_MEM_LOCAL;
index 33daf48..56e5998 100644 (file)
@@ -64,7 +64,7 @@ static drm_bo_driver_t i915_bo_driver = {
        .fence_type = i915_fence_types,
        .invalidate_caches = i915_invalidate_caches,
        .init_mem_type = i915_init_mem_type,
-       .evict_flags = i915_evict_flags,
+       .evict_mask = i915_evict_mask,
        .move = i915_move,
 };
 #endif
index 34875db..3cb1a57 100644 (file)
@@ -196,11 +196,11 @@ extern int i915_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags)
 #ifdef I915_HAVE_BUFFER
 /* i915_buffer.c */
 extern drm_ttm_backend_t *i915_create_ttm_backend_entry(drm_device_t *dev);
-extern int i915_fence_types(uint32_t buffer_flags, uint32_t *class, uint32_t *type);
+extern int i915_fence_types(drm_buffer_object_t *bo, uint32_t *class, uint32_t *type);
 extern int i915_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags);
-extern int i915_init_mem_type(drm_device_t *dev, uint32_t type, 
+extern int i915_init_mem_type(drm_device_t *dev, uint32_t type,
                               drm_mem_type_manager_t *man);
-extern uint32_t i915_evict_flags(drm_device_t *dev, uint32_t type);
+extern uint32_t i915_evict_mask(drm_buffer_object_t *bo);
 extern int i915_move(drm_buffer_object_t *bo, int evict,
                int no_wait, drm_bo_mem_reg_t *new_mem);
 
index 0915963..8c5a5c6 100644 (file)
 #include "via_drv.h"
 #include "via_3d_reg.h"
 
-#define CMDBUF_ALIGNMENT_SIZE   (0x100)
-#define CMDBUF_ALIGNMENT_MASK   (0x0ff)
-
-/* defines for VIA 3D registers */
-#define VIA_REG_STATUS   0x400
-#define VIA_REG_TRANSET         0x43C
-#define VIA_REG_TRANSPACE       0x440
-
-/* VIA_REG_STATUS(0x400): Engine Status */
-#define VIA_CMD_RGTR_BUSY       0x00000080     /* Command Regulator is busy */
-#define VIA_2D_ENG_BUSY         0x00000001     /* 2D Engine is busy */
-#define VIA_3D_ENG_BUSY         0x00000002     /* 3D Engine is busy */
-#define VIA_VR_QUEUE_BUSY       0x00020000     /* Virtual Queue is busy */
-
 #define SetReg2DAGP(nReg, nData) {                             \
        *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1;  \
        *((uint32_t *)(vb) + 1) = (nData);                      \
index 88345bd..635e463 100644 (file)
                                      (VIA_MAX_CACHELINE_SIZE - 1)) &   \
                                     ~(VIA_MAX_CACHELINE_SIZE - 1)) +   \
                                    VIA_MAX_CACHELINE_SIZE*(lockNo)))
-
-/* Each region is a minimum of 64k, and there are at most 64 of them.
- */
 #define VIA_NR_TEX_REGIONS 64
-#define VIA_LOG_MIN_TEX_REGION_SIZE 16
+
 #endif
 
-#define VIA_UPLOAD_TEX0IMAGE  0x1      /* handled clientside */
-#define VIA_UPLOAD_TEX1IMAGE  0x2      /* handled clientside */
-#define VIA_UPLOAD_CTX 0x4
-#define VIA_UPLOAD_BUFFERS    0x8
-#define VIA_UPLOAD_TEX0       0x10
-#define VIA_UPLOAD_TEX1       0x20
-#define VIA_UPLOAD_CLIPRECTS  0x40
-#define VIA_UPLOAD_ALL 0xff
+#define DRM_VIA_FENCE_TYPE_ACCEL 0x00000002
 
 /* VIA specific ioctls */
 #define DRM_VIA_ALLOCMEM       0x00
index 1446af2..0a478fe 100644 (file)
@@ -38,6 +38,47 @@ static struct pci_device_id pciidlist[] = {
        viadrv_PCI_IDS
 };
 
+
+#ifdef VIA_HAVE_FENCE
+static drm_fence_driver_t via_fence_driver = {
+       .num_classes = 1,
+       .wrap_diff = (1 << 30),
+       .flush_diff = (1 << 20),
+       .sequence_mask = 0xffffffffU,
+       .lazy_capable = 1,
+       .emit = via_fence_emit_sequence,
+       .poke_flush = via_poke_flush,
+       .has_irq = via_fence_has_irq,
+};
+#endif
+#ifdef VIA_HAVE_BUFFER
+
+/**
+ * If there's no thrashing. This is the preferred memory type order.
+ */
+static uint32_t via_mem_prios[] = {DRM_BO_MEM_PRIV0, DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
+
+/**
+ * If we have thrashing, most memory will be evicted to TT anyway, so we might as well
+ * just move the new buffer into TT from the start.
+ */
+static uint32_t via_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
+
+
+static drm_bo_driver_t via_bo_driver = {
+       .mem_type_prio = via_mem_prios,
+       .mem_busy_prio = via_busy_prios,
+       .num_mem_type_prio = ARRAY_SIZE(via_mem_prios),
+       .num_mem_busy_prio = ARRAY_SIZE(via_busy_prios),
+       .create_ttm_backend_entry = via_create_ttm_backend_entry,
+       .fence_type = via_fence_types,
+       .invalidate_caches = via_invalidate_caches,
+       .init_mem_type = via_init_mem_type,
+       .evict_mask = via_evict_mask,
+       .move = NULL,
+};
+#endif
+
 static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static struct drm_driver driver = {
        .driver_features =
@@ -80,7 +121,12 @@ static struct drm_driver driver = {
                .probe = probe,
                .remove = __devexit_p(drm_cleanup_pci),
        },
-
+#ifdef VIA_HAVE_FENCE
+       .fence_driver = &via_fence_driver,
+#endif
+#ifdef VIA_HAVE_BUFFER
+       .bo_driver = &via_bo_driver,
+#endif
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
        .date = VIA_DRM_DRIVER_DATE,
index 42d0c74..baafbbf 100644 (file)
 
 #include "via_verifier.h"
 
+/*
+ * Registers go here.
+ */
+
+
+#define CMDBUF_ALIGNMENT_SIZE   (0x100)
+#define CMDBUF_ALIGNMENT_MASK   (0x0ff)
+
+/* defines for VIA 3D registers */
+#define VIA_REG_STATUS         0x400
+#define VIA_REG_TRANSET                0x43C
+#define VIA_REG_TRANSPACE       0x440
+
+/* VIA_REG_STATUS(0x400): Engine Status */
+#define VIA_CMD_RGTR_BUSY       0x00000080     /* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY                0x00000001      /* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY                0x00000002      /* 3D Engine is busy */
+#define VIA_VR_QUEUE_BUSY       0x00020000     /* Virtual Queue is busy */
+
+
+
 #if defined(__linux__)
 #include "via_dmablit.h"
 
@@ -41,6 +62,8 @@
  */
 #define VIA_HAVE_DMABLIT 1
 #define VIA_HAVE_CORE_MM 1
+#define VIA_HAVE_FENCE   1
+#define VIA_HAVE_BUFFER  1
 #endif
 
 #define VIA_PCI_BUF_SIZE 60000
@@ -103,6 +126,12 @@ typedef struct drm_via_private {
        drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
 #endif
         uint32_t dma_diff;
+#ifdef VIA_HAVE_FENCE
+       spinlock_t fence_lock;
+       uint32_t emit_0_sequence;
+       int have_idlelock;
+       struct timer_list fence_timer;
+#endif
 } drm_via_private_t;
 
 enum via_family {
@@ -163,4 +192,26 @@ extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
 extern void via_init_dmablit(drm_device_t *dev);
 #endif
 
+#ifdef VIA_HAVE_FENCE
+extern void via_fence_timer(unsigned long data);
+extern void via_poke_flush(drm_device_t * dev, uint32_t class);
+extern int via_fence_emit_sequence(drm_device_t * dev, uint32_t class,
+                                  uint32_t flags,
+                                  uint32_t * sequence,
+                                  uint32_t * native_type);
+extern int via_fence_has_irq(struct drm_device * dev, uint32_t class,
+                            uint32_t flags);
+#endif
+
+#ifdef VIA_HAVE_BUFFER
+extern drm_ttm_backend_t *via_create_ttm_backend_entry(drm_device_t *dev);
+extern int via_fence_types(drm_buffer_object_t *bo, uint32_t *class, uint32_t *type);
+extern int via_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags);
+extern int via_init_mem_type(drm_device_t *dev, uint32_t type,
+                              drm_mem_type_manager_t *man);
+extern uint32_t via_evict_mask(drm_buffer_object_t *bo);
+extern int via_move(drm_buffer_object_t *bo, int evict,
+               int no_wait, drm_bo_mem_reg_t *new_mem);
+#endif
+
 #endif
index a37f5fd..83324cf 100644 (file)
@@ -28,6 +28,7 @@
 static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
+       int ret = 0;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
@@ -64,8 +65,22 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
 #ifdef VIA_HAVE_DMABLIT
        via_init_dmablit( dev );
 #endif
+#ifdef VIA_HAVE_FENCE
+       dev_priv->emit_0_sequence = 0;
+       dev_priv->have_idlelock = 0;
+       spin_lock_init(&dev_priv->fence_lock);
+       init_timer(&dev_priv->fence_timer);
+       dev_priv->fence_timer.function = &via_fence_timer;
+       dev_priv->fence_timer.data = (unsigned long) dev;
+#endif /* VIA_HAVE_FENCE */
        dev->dev_private = (void *)dev_priv;
-       return 0;
+#ifdef VIA_HAVE_BUFFER
+       ret = drm_bo_driver_init(dev);
+       if (ret)
+               DRM_ERROR("Could not initialize buffer object driver.\n");
+#endif
+       return ret;
+
 }
 
 int via_do_cleanup_map(drm_device_t * dev)