summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2007-02-16 20:22:24 +0100
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2007-02-16 20:22:24 +0100
commite0f53e59be4b96ed6eb28bd2df9f6a9d789d1734 (patch)
tree3989201a990ef5ab87b31da3655109c6c30cfbea
parent7766378d97323de375687285f2e125008b79045d (diff)
Simple fence object sample driver for via, based on idling the GPU.
Buffer object driver for via. Some changes to buffer object driver callbacks. Improve fence flushing.
-rw-r--r--libdrm/xf86drm.c3
-rw-r--r--linux-core/Makefile.kernel4
-rw-r--r--linux-core/drm_bo.c11
-rw-r--r--linux-core/drm_fence.c15
-rw-r--r--linux-core/drm_objects.h4
-rw-r--r--linux-core/i915_buffer.c8
-rw-r--r--linux-core/i915_drv.c2
-rw-r--r--shared-core/i915_drv.h6
-rw-r--r--shared-core/via_dma.c14
-rw-r--r--shared-core/via_drm.h14
-rw-r--r--shared-core/via_drv.c48
-rw-r--r--shared-core/via_drv.h51
-rw-r--r--shared-core/via_map.c17
13 files changed, 146 insertions, 51 deletions
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index 1a8edeef..862772d5 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -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;
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index c2bfb671..08c0fb2a 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -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)
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 8fc2a30e..548ce14f 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -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
diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c
index 634cf4f7..3e17a16d 100644
--- a/linux-core/drm_fence.c
+++ b/linux-core/drm_fence.c
@@ -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.
*/
diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h
index 547de6b4..98228ada 100644
--- a/linux-core/drm_objects.h
+++ b/linux-core/drm_objects.h
@@ -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;
diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c
index 2cb0dc5f..8797de89 100644
--- a/linux-core/i915_buffer.c
+++ b/linux-core/i915_buffer.c
@@ -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;
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index 33daf480..56e5998f 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -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
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 34875db8..3cb1a573 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -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);
diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c
index 09159634..8c5a5c64 100644
--- a/shared-core/via_dma.c
+++ b/shared-core/via_dma.c
@@ -40,20 +40,6 @@
#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); \
diff --git a/shared-core/via_drm.h b/shared-core/via_drm.h
index 88345bdf..635e4637 100644
--- a/shared-core/via_drm.h
+++ b/shared-core/via_drm.h
@@ -58,21 +58,11 @@
(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
diff --git a/shared-core/via_drv.c b/shared-core/via_drv.c
index 1446af2c..0a478fef 100644
--- a/shared-core/via_drv.c
+++ b/shared-core/via_drv.c
@@ -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,
diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h
index 42d0c749..baafbbff 100644
--- a/shared-core/via_drv.h
+++ b/shared-core/via_drv.h
@@ -32,6 +32,27 @@
#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
diff --git a/shared-core/via_map.c b/shared-core/via_map.c
index a37f5fd2..83324cfa 100644
--- a/shared-core/via_map.c
+++ b/shared-core/via_map.c
@@ -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)