From e0f53e59be4b96ed6eb28bd2df9f6a9d789d1734 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 16 Feb 2007 20:22:24 +0100 Subject: 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. --- libdrm/xf86drm.c | 3 ++- linux-core/Makefile.kernel | 4 ++-- linux-core/drm_bo.c | 11 +++++----- linux-core/drm_fence.c | 15 +++++++++----- linux-core/drm_objects.h | 4 ++-- linux-core/i915_buffer.c | 8 ++++---- linux-core/i915_drv.c | 2 +- shared-core/i915_drv.h | 6 +++--- shared-core/via_dma.c | 14 ------------- shared-core/via_drm.h | 14 ++----------- shared-core/via_drv.c | 48 ++++++++++++++++++++++++++++++++++++++++++- shared-core/via_drv.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++ shared-core/via_map.c | 17 +++++++++++++++- 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) -- cgit v1.2.3