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.
main
Thomas Hellstrom 2007-02-16 20:22:24 +01:00
parent 7766378d97
commit e0f53e59be
13 changed files with 146 additions and 51 deletions

View File

@ -2273,6 +2273,7 @@ int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
drm_fence_arg_t arg; drm_fence_arg_t arg;
memset(&arg, 0, sizeof(arg)); memset(&arg, 0, sizeof(arg));
arg.flags = flags;
arg.type = type; arg.type = type;
arg.class = class; arg.class = class;
arg.op = drm_fence_create; arg.op = drm_fence_create;

View File

@ -29,7 +29,7 @@ sis-objs := sis_drv.o sis_mm.o
ffb-objs := ffb_drv.o ffb_context.o ffb-objs := ffb_drv.o ffb_context.o
savage-objs := savage_drv.o savage_bci.o savage_state.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-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 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 mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
nv-objs := nv_drv.o nv-objs := nv_drv.o

View File

@ -641,7 +641,7 @@ static int drm_bo_evict(drm_buffer_object_t * bo, unsigned mem_type,
} }
evict_mem = bo->mem; 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); ret = drm_bo_mem_space(bo, &evict_mem, no_wait);
if (ret) { 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, DRM_DEBUG("New flags 0x%08x, Old flags 0x%08x\n", bo->mem.mask,
bo->mem.flags); bo->mem.flags);
ret = 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) { if (ret) {
DRM_ERROR("Driver did not support given buffer permissions\n"); DRM_ERROR("Driver did not support given buffer permissions\n");
return ret; return ret;
@ -2001,7 +2001,7 @@ static int drm_bo_lock_mm(drm_device_t * dev, unsigned mem_type)
return ret; return ret;
} }
static int drm_bo_init_mm(drm_device_t * dev, int drm_bo_init_mm(drm_device_t * dev,
unsigned type, unsigned type,
unsigned long p_offset, unsigned long p_size) unsigned long p_offset, unsigned long p_size)
{ {
@ -2043,6 +2043,7 @@ static int drm_bo_init_mm(drm_device_t * dev,
return 0; return 0;
} }
EXPORT_SYMBOL(drm_bo_init_mm);
/* /*
* This is called from lastclose, so we don't need to bother about * This is called from lastclose, so we don't need to bother about

View 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) { if (wake) {
DRM_WAKEUP(&fc->fence_queue); DRM_WAKEUP(&fc->fence_queue);
} }
@ -180,7 +185,7 @@ static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
*/ */
list = &fc->ring; list = &fc->ring;
if (list->next == &fc->ring) { if (list_empty(list)) {
return; return;
} else { } else {
drm_fence_object_t *fence = 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, static int drm_fence_lazy_wait(drm_device_t *dev,
drm_fence_object_t *fence, 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_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[fence->class]; 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 { do {
DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ, 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)) if (time_after_eq(jiffies, _end))
break; break;
} while (ret == -EINTR && ignore_signals); } while (ret == -EINTR && ignore_signals);
@ -352,10 +358,9 @@ int drm_fence_object_wait(drm_device_t * dev,
return ret; return ret;
} }
} }
if (fence_signaled(dev, fence, mask, 0)) if (drm_fence_object_signaled(fence, mask))
return 0; return 0;
DRM_ERROR("Busy wait\n");
/* /*
* Avoid kernel-space busy-waits. * Avoid kernel-space busy-waits.
*/ */

View File

@ -411,11 +411,11 @@ typedef struct drm_bo_driver {
uint32_t num_mem_busy_prio; uint32_t num_mem_busy_prio;
drm_ttm_backend_t *(*create_ttm_backend_entry) drm_ttm_backend_t *(*create_ttm_backend_entry)
(struct drm_device * dev); (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 (*invalidate_caches) (struct drm_device * dev, uint32_t flags);
int (*init_mem_type) (struct drm_device * dev, uint32_t type, int (*init_mem_type) (struct drm_device * dev, uint32_t type,
drm_mem_type_manager_t * man); 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 (*move) (struct drm_buffer_object * bo,
int evict, int no_wait, struct drm_bo_mem_reg * new_mem); int evict, int no_wait, struct drm_bo_mem_reg * new_mem);
} drm_bo_driver_t; } drm_bo_driver_t;

View 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); 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; *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; *type = 3;
else else
*type = 1; *type = 1;
@ -106,9 +106,9 @@ int i915_init_mem_type(drm_device_t * dev, uint32_t type,
return 0; 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_LOCAL:
case DRM_BO_MEM_TT: case DRM_BO_MEM_TT:
return DRM_BO_FLAG_MEM_LOCAL; return DRM_BO_FLAG_MEM_LOCAL;

View File

@ -64,7 +64,7 @@ static drm_bo_driver_t i915_bo_driver = {
.fence_type = i915_fence_types, .fence_type = i915_fence_types,
.invalidate_caches = i915_invalidate_caches, .invalidate_caches = i915_invalidate_caches,
.init_mem_type = i915_init_mem_type, .init_mem_type = i915_init_mem_type,
.evict_flags = i915_evict_flags, .evict_mask = i915_evict_mask,
.move = i915_move, .move = i915_move,
}; };
#endif #endif

View 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 #ifdef I915_HAVE_BUFFER
/* i915_buffer.c */ /* i915_buffer.c */
extern drm_ttm_backend_t *i915_create_ttm_backend_entry(drm_device_t *dev); 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_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); 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, extern int i915_move(drm_buffer_object_t *bo, int evict,
int no_wait, drm_bo_mem_reg_t *new_mem); int no_wait, drm_bo_mem_reg_t *new_mem);

View File

@ -40,20 +40,6 @@
#include "via_drv.h" #include "via_drv.h"
#include "via_3d_reg.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) { \ #define SetReg2DAGP(nReg, nData) { \
*((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \ *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \
*((uint32_t *)(vb) + 1) = (nData); \ *((uint32_t *)(vb) + 1) = (nData); \

View File

@ -58,21 +58,11 @@
(VIA_MAX_CACHELINE_SIZE - 1)) & \ (VIA_MAX_CACHELINE_SIZE - 1)) & \
~(VIA_MAX_CACHELINE_SIZE - 1)) + \ ~(VIA_MAX_CACHELINE_SIZE - 1)) + \
VIA_MAX_CACHELINE_SIZE*(lockNo))) 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_NR_TEX_REGIONS 64
#define VIA_LOG_MIN_TEX_REGION_SIZE 16
#endif #endif
#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ #define DRM_VIA_FENCE_TYPE_ACCEL 0x00000002
#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
/* VIA specific ioctls */ /* VIA specific ioctls */
#define DRM_VIA_ALLOCMEM 0x00 #define DRM_VIA_ALLOCMEM 0x00

View File

@ -38,6 +38,47 @@ static struct pci_device_id pciidlist[] = {
viadrv_PCI_IDS 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 int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static struct drm_driver driver = { static struct drm_driver driver = {
.driver_features = .driver_features =
@ -80,7 +121,12 @@ static struct drm_driver driver = {
.probe = probe, .probe = probe,
.remove = __devexit_p(drm_cleanup_pci), .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, .name = DRIVER_NAME,
.desc = DRIVER_DESC, .desc = DRIVER_DESC,
.date = VIA_DRM_DRIVER_DATE, .date = VIA_DRM_DRIVER_DATE,

View File

@ -32,6 +32,27 @@
#include "via_verifier.h" #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__) #if defined(__linux__)
#include "via_dmablit.h" #include "via_dmablit.h"
@ -41,6 +62,8 @@
*/ */
#define VIA_HAVE_DMABLIT 1 #define VIA_HAVE_DMABLIT 1
#define VIA_HAVE_CORE_MM 1 #define VIA_HAVE_CORE_MM 1
#define VIA_HAVE_FENCE 1
#define VIA_HAVE_BUFFER 1
#endif #endif
#define VIA_PCI_BUF_SIZE 60000 #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]; drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
#endif #endif
uint32_t dma_diff; 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; } drm_via_private_t;
enum via_family { 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); extern void via_init_dmablit(drm_device_t *dev);
#endif #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 #endif

View File

@ -28,6 +28,7 @@
static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init) static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
{ {
drm_via_private_t *dev_priv = dev->dev_private; drm_via_private_t *dev_priv = dev->dev_private;
int ret = 0;
DRM_DEBUG("%s\n", __FUNCTION__); 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 #ifdef VIA_HAVE_DMABLIT
via_init_dmablit( dev ); via_init_dmablit( dev );
#endif #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; 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) int via_do_cleanup_map(drm_device_t * dev)