summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Hartmann <jhartmann@valinux.com>2000-02-22 00:01:59 +0000
committerJeff Hartmann <jhartmann@valinux.com>2000-02-22 00:01:59 +0000
commit2753541c30e1c978c4a32598209d2fe0ead41722 (patch)
treebb04686c920abf1096ad8a64445f523daa1fbd27
parent122f75065cebe721137daaa7c4b26fedb21a499e (diff)
Performance tuning
-rw-r--r--linux/mga_dma.c58
-rw-r--r--linux/mga_dma.h2
-rw-r--r--linux/mga_drv.h2
-rw-r--r--linux/mga_state.c3
4 files changed, 52 insertions, 13 deletions
diff --git a/linux/mga_dma.c b/linux/mga_dma.c
index e951f6fc..f5e06775 100644
--- a/linux/mga_dma.c
+++ b/linux/mga_dma.c
@@ -328,6 +328,7 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
}
mga_flush_write_combine();
+ atomic_inc(&dev_priv->pending_bufs);
MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
}
@@ -337,6 +338,7 @@ int mga_advance_primary(drm_device_t *dev)
DECLARE_WAITQUEUE(entry, current);
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_prim_buf_t *prim_buffer;
+ drm_device_dma_t *dma = dev->dma;
int next_prim_idx;
int ret = 0;
@@ -350,18 +352,13 @@ int mga_advance_primary(drm_device_t *dev)
/* In use is cleared in interrupt handler */
atomic_set(&dev_priv->in_wait, 1);
if(test_and_set_bit(0, &prim_buffer->in_use)) {
- /* We need to wait, we should probably use
- * a wait queue for this.
- */
add_wait_queue(&dev_priv->wait_queue, &entry);
for (;;) {
current->state = TASK_INTERRUPTIBLE;
mga_dma_schedule(dev, 0);
if(!test_and_set_bit(0, &prim_buffer->in_use)) break;
atomic_inc(&dev->total_sleeps);
-#if 0
- schedule_timeout(HZ/60);
-#endif
+ atomic_inc(&dma->total_missed_sched);
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
@@ -382,6 +379,41 @@ int mga_advance_primary(drm_device_t *dev)
return 0;
}
+/* More dynamic performance decisions */
+static inline int mga_decide_to_fire(drm_device_t *dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+
+ if(atomic_read(&dev_priv->next_prim->force_fire) ||
+ (atomic_read(&dev_priv->in_flush) && dev_priv->next_prim->num_dwords)) {
+ atomic_inc(&dma->total_prio);
+ return 1;
+ }
+ if(atomic_read(&dev_priv->pending_bufs) <= (MGA_NUM_PRIM_BUFS - 3)) {
+
+ if(test_bit(0, &dev_priv->next_prim->swap_pending)) {
+ atomic_inc(&dma->total_dmas);
+ return 1;
+ }
+ }
+ if(atomic_read(&dev_priv->pending_bufs) <= (MGA_NUM_PRIM_BUFS / 2)) {
+ if(dev_priv->next_prim->sec_used >= (MGA_DMA_BUF_NR / 8)) {
+ atomic_inc(&dma->total_hit);
+ return 1;
+ }
+ }
+ if(atomic_read(&dev_priv->pending_bufs) >= (MGA_NUM_PRIM_BUFS / 2)) {
+ if(dev_priv->next_prim->sec_used >= (MGA_DMA_BUF_NR / 4)) {
+ atomic_inc(&dma->total_missed_free);
+ return 1;
+ }
+ }
+
+ atomic_inc(&dma->total_tried);
+ return 0;
+}
+
int mga_dma_schedule(drm_device_t *dev, int locked)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
@@ -407,9 +439,7 @@ int mga_dma_schedule(drm_device_t *dev, int locked)
if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) {
/* Fire dma buffer */
- if(dev_priv->next_prim->sec_used >= (MGA_DMA_BUF_NR / 2) ||
- (dev_priv->next_prim->num_dwords && atomic_read(&dev_priv->in_flush)) ||
- atomic_read(&dev_priv->next_prim->force_fire)) {
+ if(mga_decide_to_fire(dev)) {
DRM_DEBUG("mga_fire_primary\n");
atomic_set(&dev_priv->next_prim->force_fire, 0);
if(dev_priv->current_prim == dev_priv->next_prim) {
@@ -455,16 +485,17 @@ static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
last_prim_buffer = dev_priv->prim_bufs[softrap_idx];
dev_priv->last_prim = last_prim_buffer;
last_prim_buffer->num_dwords = 0;
+ last_prim_buffer->sec_used = 0;
clear_bit(0, &last_prim_buffer->in_use);
+ clear_bit(0, &last_prim_buffer->swap_pending);
clear_bit(0, &dev_priv->dispatch_lock);
+ atomic_dec(&dev_priv->pending_bufs);
queue_task(&dev->tq, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
static void mga_dma_task_queue(void *device)
{
- /* This needs to do primary buffer ping-ponging as well
- * as flushing */
drm_device_t *dev = (drm_device_t *) device;
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
@@ -853,6 +884,7 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
*/
if (!ret) {
+#if 0
if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
== lock.context && _DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) {
long j = jiffies - dev->lock.lock_time;
@@ -864,6 +896,7 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
schedule_timeout(j);
}
}
+#endif
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
if (!dev->lock.hw_lock) {
@@ -911,8 +944,11 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp,
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+
DRM_DEBUG("mga_flush_ioctl\n");
+ atomic_inc(&dma->total_lost);
mga_flush_queue(dev);
return 0;
}
diff --git a/linux/mga_dma.h b/linux/mga_dma.h
index 8cb672ce..f844c39d 100644
--- a/linux/mga_dma.h
+++ b/linux/mga_dma.h
@@ -33,7 +33,7 @@ typedef struct {
#define MGA_VERBOSE 0
-#define MGA_NUM_PRIM_BUFS 16
+#define MGA_NUM_PRIM_BUFS 8
/* Primary buffer versions of above -- pretty similar really.
*/
diff --git a/linux/mga_drv.h b/linux/mga_drv.h
index b416c557..1e9e0a82 100644
--- a/linux/mga_drv.h
+++ b/linux/mga_drv.h
@@ -41,6 +41,7 @@ typedef struct {
u32 phys_head;
int sec_used;
int idx;
+ int swap_pending;
u32 in_use;
atomic_t force_fire;
} drm_mga_prim_buf_t;
@@ -67,6 +68,7 @@ typedef struct _drm_mga_private {
u32 dispatch_lock;
atomic_t in_flush;
atomic_t in_wait;
+ atomic_t pending_bufs;
unsigned int last_sync_tag;
unsigned int sync_tag;
void *status_page;
diff --git a/linux/mga_state.c b/linux/mga_state.c
index 72ad8d28..983a44b8 100644
--- a/linux/mga_state.c
+++ b/linux/mga_state.c
@@ -779,7 +779,8 @@ int mga_swap_bufs(struct inode *inode, struct file *filp,
dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
mga_dma_dispatch_swap( dev );
PRIMUPDATE(dev_priv);
- atomic_set(&dev_priv->current_prim->force_fire, 1);
+ set_bit(0, &dev_priv->current_prim->swap_pending);
+ dev_priv->current_prim->swap_pending = 1;
mga_dma_schedule(dev, 1);
sarea_priv->last_dispatch = status[1];
return 0;