openchrome: Add deferred fence emission.

This commit is contained in:
Thomas Hellstrom 2009-03-02 18:22:11 +01:00 committed by Thomas Hellstrom
parent bcfe35e32c
commit 780e793629
6 changed files with 80 additions and 26 deletions

View file

@ -60,7 +60,7 @@
dev_priv->dma_low += 8; \
}
#define VIA_TRACKER_INTERVAL 0x10000
#define VIA_TRACKER_INTERVAL 0x100000
struct via_dma_tracker {
struct list_head head;
@ -110,16 +110,18 @@ static inline int via_cmdbuf_wait(struct drm_via_private *dev_priv,
return 0;
}
static bool via_no_tracker(struct drm_via_private *dev_priv)
{
via_traverse_trackers(dev_priv);
return (((dev_priv->dma_low - dev_priv->dma_tracker) & VIA_AGPC_MASK) <
VIA_TRACKER_INTERVAL);
}
static int via_add_tracker(struct drm_via_private *dev_priv, uint32_t sequence)
{
struct via_dma_tracker *tracker;
if (likely
(((dev_priv->dma_low - dev_priv->dma_tracker) & VIA_AGPC_MASK) <
VIA_TRACKER_INTERVAL))
return 0;
via_traverse_trackers(dev_priv);
dev_priv->dma_tracker = dev_priv->dma_low;
tracker = kmalloc(sizeof(*tracker), GFP_KERNEL);
@ -192,13 +194,8 @@ static void via_emit_blit_sequence(struct drm_via_private *dev_priv,
VIA_OUT_RING_H1(VIA_REG_DIMENSION, 0);
VIA_OUT_RING_H1(VIA_REG_GECMD, VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT
| (VIA_ROP_PAT << 24));
#if 0
VIA_OUT_RING_QW(VIA_VIDEO_HEADER6, 0x00000002);
VIA_OUT_RING_QW(0x00F60000, 0x00000000);
VIA_OUT_RING_QW(0x326C, (3 << 30) | (0x1f << 25));
VIA_OUT_RING_QW(0x33D0, (1 << 27) | (1 << 7) | (1 << 6) |
(1 << 4) | (1 << 0));
#endif
atomic_set(&dev_priv->emitted_cmd_seq, value);
}
static void via_blit_sequence(struct drm_via_private *dev_priv,
@ -215,6 +212,8 @@ static void via_blit_sequence(struct drm_via_private *dev_priv,
VIA_WRITE(VIA_REG_DIMENSION, 0);
VIA_WRITE(VIA_REG_GECMD, VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT
| (VIA_ROP_PAT << 24));
atomic_set(&dev_priv->emitted_cmd_seq, value);
}
/*
@ -610,7 +609,7 @@ int via_copy_cmdbuf(struct drm_via_private *dev_priv,
}
int via_dispatch_commands(struct drm_device *dev, unsigned long size,
uint32_t mechanism)
uint32_t mechanism, bool emit_seq)
{
struct drm_via_private *dev_priv = via_priv(dev);
uint32_t *vb;
@ -630,8 +629,11 @@ int via_dispatch_commands(struct drm_device *dev, unsigned long size,
dev_priv->dma_low += size;
seq =
atomic_add_return(1, &dev_priv->fence_seq[VIA_ENGINE_CMD]);
via_emit_fence_seq(dev_priv, VIA_FENCE_OFFSET_CMD, seq);
via_add_tracker(dev_priv, seq);
if (emit_seq || !via_no_tracker(dev_priv)) {
via_emit_fence_seq(dev_priv, VIA_FENCE_OFFSET_CMD, seq);
via_add_tracker(dev_priv, seq);
}
via_cmdbuf_pause(dev_priv);
return 0;
case _VIA_MECHANISM_PCI:
@ -641,9 +643,11 @@ int via_dispatch_commands(struct drm_device *dev, unsigned long size,
size);
seq =
atomic_add_return(1, &dev_priv->fence_seq[VIA_ENGINE_CMD]);
via_wait_idle(dev_priv);
via_blit_sequence(dev_priv, VIA_FENCE_OFFSET_CMD, seq);
via_wait_idle(dev_priv);
if (emit_seq) {
via_wait_idle(dev_priv);
via_blit_sequence(dev_priv, VIA_FENCE_OFFSET_CMD, seq);
via_wait_idle(dev_priv);
}
return ret;
default:
return -EINVAL;

View file

@ -179,6 +179,7 @@ struct drm_via_private {
struct drm_via_blitq blit_queues[VIA_NUM_BLIT_ENGINES];
uint32_t dma_diff;
atomic_t fence_seq[VIA_NUM_ENGINES];
atomic_t emitted_cmd_seq;
uint64_t vram_size; /* kiB */
uint64_t vram_start;
int vram_direct;
@ -262,6 +263,8 @@ extern void via_driver_irq_preinstall(struct drm_device *dev);
extern int via_driver_irq_postinstall(struct drm_device *dev);
extern void via_driver_irq_uninstall(struct drm_device *dev);
extern void via_emit_fence_seq_standalone(struct drm_via_private *dev_priv,
uint32_t offset, uint32_t value);
extern int via_dma_cleanup(struct drm_device *dev);
extern void via_init_command_verifier(void);
extern int via_driver_dma_quiescent(struct drm_device *dev);
@ -298,7 +301,8 @@ extern int via_vt_ioctl(struct drm_device *dev, void *data,
extern int via_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int via_dispatch_commands(struct drm_device *dev,
unsigned long size, uint32_t mechanism);
unsigned long size, uint32_t mechanism,
bool emit_seq);
extern void via_ttm_signal_fences(struct drm_via_private *dev_priv);
extern void via_ttm_fence_cmd_handler(struct drm_via_private *dev_priv, uint32_t signal_types);
extern void via_ttm_fence_dmablit_handler(struct drm_via_private *dev_priv, int engine);

View file

@ -733,6 +733,7 @@ static int via_dispatch_clip(struct drm_device *dev,
uint32_t i;
uint64_t cliprect_addr = 0;
int ret = 0;
bool emit_seq;
if (exec_buf->exec_flags & DRM_VIA_HAVE_CLIP) {
first_clip = control->first_clip;
@ -746,6 +747,9 @@ static int via_dispatch_clip(struct drm_device *dev,
}
for (i = first_clip; i < num_clip; ++i) {
emit_seq = ((i == num_clip - 1) &&
!(exec_buf->exec_flags & DRM_VIA_DEFER_FENCING));
if (i > first_clip && drm_via_disable_verifier &&
exec_buf->mechanism == _VIA_MECHANISM_AGP) {
ret = via_copy_cmdbuf(dev_priv, exec_buf->cmd_buffer,
@ -790,7 +794,7 @@ static int via_dispatch_clip(struct drm_device *dev,
}
ret = via_dispatch_commands(dev, exec_buf->cmd_buffer_size,
exec_buf->mechanism);
exec_buf->mechanism, emit_seq);
if (unlikely(ret != 0))
goto out;

View file

@ -666,8 +666,9 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->fence_timer.function = via_ttm_fence_timer_func;
for (i = 0; i < VIA_NUM_ENGINES; ++i) {
atomic_set(&dev_priv->fence_seq[i], 0);
atomic_set(&dev_priv->fence_seq[i], -100);
}
atomic_set(&dev_priv->emitted_cmd_seq, -100);
ret = via_setup_mmio_map(dev);
if (ret)

View file

@ -206,12 +206,52 @@ enum hrtimer_restart via_ttm_fence_timer_func(struct hrtimer *timer)
return HRTIMER_NORESTART;
}
/**
* Since emitting a sequence blit after each command submission has a
* negative performance impact, we defer that emission until fence flushing.
*/
static void via_ttm_fence_flush(struct ttm_fence_device *fdev,
uint32_t fence_class)
{
if (fence_class == VIA_ENGINE_CMD) {
struct drm_via_private *dev_priv =
container_of(fdev, struct drm_via_private, fdev);
uint32_t sequence;
mutex_lock(&dev_priv->cmdbuf_mutex);
sequence = atomic_read(&dev_priv->fence_seq[VIA_ENGINE_CMD]);
via_emit_fence_seq_standalone(dev_priv, VIA_FENCE_OFFSET_CMD,
sequence);
DRM_INFO("Flushing fence 0x%08x\n", (unsigned) sequence);
mutex_unlock(&dev_priv->cmdbuf_mutex);
}
}
/**
* If the fence sequence is higher than what we've actually put in the
* command stream, indicate that we need to flush this fence type.
*/
static uint32_t via_ttm_fence_needed_flush(struct ttm_fence_object *fence)
{
struct ttm_fence_device *fdev = fence->fdev;
struct ttm_fence_class_manager *fc = &fdev->fence_class[VIA_ENGINE_CMD];
struct drm_via_private *dev_priv =
container_of(fdev, struct drm_via_private, fdev);
uint32_t diff = (uint32_t) atomic_read(&dev_priv->emitted_cmd_seq) -
fence->sequence;
return (diff > fc->wrap_diff) ? TTM_FENCE_TYPE_EXE : 0;
}
static struct ttm_fence_driver via_ttm_fence_driver = {
.has_irq = via_ttm_fence_has_irq,
.emit = via_ttm_fence_emit_sequence,
.flush = NULL,
.flush = via_ttm_fence_flush,
.poll = via_ttm_fence_poll,
.needed_flush = NULL,
.needed_flush = via_ttm_fence_needed_flush,
.wait = NULL,
.signaled = NULL,
};

View file

@ -35,7 +35,7 @@
#define DRM_VIA_DRIVER_DATE "20090119"
#define DRM_VIA_DRIVER_MAJOR 0
#define DRM_VIA_DRIVER_MINOR 1
#define DRM_VIA_DRIVER_MINOR 2
#define DRM_VIA_DRIVER_PATCHLEVEL 0
#define DRM_VIA_DRIVER_VERSION (((VIA_DRM_DRIVER_MAJOR) << 16) | (VIA_DRM_DRIVER_MINOR))
@ -361,6 +361,7 @@ struct drm_via_clip_rect {
#define DRM_VIA_HAVE_CLIP (1 << 0)
#define DRM_VIA_FENCE_NO_USER (1 << 1)
#define DRM_VIA_WAIT_BARRIER (1 << 2)
#define DRM_VIA_DEFER_FENCING (1 << 3)
struct drm_via_ttm_execbuf_control {
struct drm_via_ttm_fence_rep rep;