Bugfixes + tuning

This commit is contained in:
Jeff Hartmann 2000-02-21 19:31:27 +00:00
parent d5f181b5c5
commit 122f75065c
6 changed files with 135 additions and 89 deletions

View file

@ -67,7 +67,7 @@
#define DRM_LOOPING_LIMIT 5000000
#define DRM_BSZ 1024 /* Buffer size for /dev/drm? output */
#define DRM_TIME_SLICE (HZ/20) /* Time slice for GLXContexts */
#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */
#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */
#define DRM_FLAG_DEBUG 0x01
#define DRM_FLAG_NOCTX 0x02

View file

@ -67,7 +67,7 @@
#define DRM_LOOPING_LIMIT 5000000
#define DRM_BSZ 1024 /* Buffer size for /dev/drm? output */
#define DRM_TIME_SLICE (HZ/20) /* Time slice for GLXContexts */
#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */
#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */
#define DRM_FLAG_DEBUG 0x01
#define DRM_FLAG_NOCTX 0x02

View file

@ -49,6 +49,8 @@
#define PDEA_pagpxfer_enable 0x2
static int mga_flush_queue(drm_device_t *dev);
static unsigned long mga_alloc_page(drm_device_t *dev)
{
unsigned long address;
@ -106,13 +108,85 @@ static void mga_freelist_init(drm_device_t *dev)
}
}
unsigned int mga_create_sync_tag(drm_mga_private_t *dev_priv)
void mga_wait_usec(int waittime)
{
struct timeval timep;
int top_usec = 0;
int bot_usec = 0;
int i;
while(1) {
do_gettimeofday(&timep);
top_usec = timep.tv_usec;
if((bot_usec = 0) || (top_usec < bot_usec)) {
bot_usec = top_usec;
} else if ((top_usec - bot_usec) > waittime) {
break;
}
for(i = 0 ; i < 4096; i++) mga_delay();
}
return;
}
void mga_reset_abort(drm_device_t *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
u32 temp;
u32 reset;
pci_read_config_dword(dev_priv->device,
0x04,
&temp);
reset = temp;
reset &= 0x38000000;
if(reset != 0) {
/* Do a softreset */
DRM_ERROR("Doing a soft reset : reset %x\n", reset);
MGA_WRITE(0x1e40, 0x00000001);
mga_wait_usec(10);
MGA_WRITE(0x1e40, 0x00000000);
pci_write_config_dword(dev_priv->device,
0x04,
temp);
}
}
/* Frees dispatch lock */
static inline void mga_dma_quiescent(drm_device_t *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
__volatile__ unsigned int *status =
(__volatile__ unsigned int *)dev_priv->status_page;
while(1) {
if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) {
break;
}
}
DRM_DEBUG("quiescent status : %x\n", MGA_READ(MGAREG_STATUS));
mga_reset_abort(dev);
while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
DRM_DEBUG("status[1] : %x last_sync_tag : %x\n", status[1],
dev_priv->last_sync_tag);
sarea_priv->dirty |= MGA_DMA_FLUSH;
clear_bit(0, &dev_priv->dispatch_lock);
}
unsigned int mga_create_sync_tag(drm_device_t *dev)
{
drm_mga_private_t *dev_priv =
(drm_mga_private_t *) dev->dev_private;
unsigned int temp;
dev_priv->sync_tag++;
if(dev_priv->sync_tag > 0x3fffffff) {
/* Make sure we are always at least 1 */
mga_flush_queue(dev);
mga_dma_quiescent(dev);
dev_priv->sync_tag = 1;
/* Do a full dma flush */
}
@ -232,7 +306,7 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
int use_agp = PDEA_pagpxfer_enable;
PRIMLOCALS;
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
dev_priv->last_sync_tag = mga_create_sync_tag(dev);
/* We never check for overflow, b/c there is always room */
PRIMPTR(prim);
@ -282,10 +356,13 @@ int mga_advance_primary(drm_device_t *dev)
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);
mga_dma_schedule(dev, 0);
#if 0
schedule_timeout(HZ/60);
#endif
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
@ -314,9 +391,13 @@ int mga_dma_schedule(drm_device_t *dev, int locked)
atomic_inc(&dma->total_missed_dma);
return -EBUSY;
}
if(atomic_read(&dev_priv->in_flush) ||
atomic_read(&dev_priv->in_wait)) {
locked = 1;
}
if (!locked && !atomic_read(&dev_priv->in_flush) &&
!atomic_read(&dev_priv->in_wait) &&
if (!locked &&
!drm_lock_take(&dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT)) {
atomic_inc(&dma->total_missed_lock);
@ -342,8 +423,7 @@ int mga_dma_schedule(drm_device_t *dev, int locked)
}
}
if (!locked && !atomic_read(&dev_priv->in_flush)
&& !atomic_read(&dev_priv->in_wait)) {
if (!locked) {
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT)) {
DRM_ERROR("\n");
@ -388,8 +468,8 @@ static void mga_dma_task_queue(void *device)
drm_device_t *dev = (drm_device_t *) device;
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
wake_up_interruptible(&dev_priv->wait_queue);
mga_dma_schedule(dev, 0);
wake_up_interruptible(&dev_priv->wait_queue);
if(atomic_read(&dev_priv->in_flush) == 1 &&
dev_priv->next_prim->num_dwords == 0) {
/* Everything is on the hardware */
@ -542,7 +622,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
PRIMLOCALS;
PRIMGETPTR( dev_priv );
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
dev_priv->last_sync_tag = mga_create_sync_tag(dev);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
@ -593,73 +673,15 @@ int mga_dma_init(struct inode *inode, struct file *filp,
return -EINVAL;
}
void mga_wait_usec(int waittime)
#if 0
static int __gettimeinmillis(void)
{
struct timeval timep;
int top_usec = 0;
int bot_usec = 0;
int i;
while(1) {
do_gettimeofday(&timep);
top_usec = timep.tv_usec;
if((bot_usec = 0) || (top_usec < bot_usec)) {
bot_usec = top_usec;
} else if ((top_usec - bot_usec) > waittime) {
break;
}
for(i = 0 ; i < 4096; i++) mga_delay();
}
return;
struct timeval timep;
do_gettimeofday(&timep);
return(timep.tv_sec * 1000) + (timep.tv_usec / 1000);
}
#endif
void mga_reset_abort(drm_device_t *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
u32 temp;
u32 reset;
pci_read_config_dword(dev_priv->device,
0x04,
&temp);
reset = temp;
reset &= 0x38000000;
if(reset != 0) {
/* Do a softreset */
DRM_DEBUG("Doing a soft reset : reset %x\n", reset);
MGA_WRITE(0x1e40, 0x00000001);
mga_wait_usec(10);
MGA_WRITE(0x1e40, 0x00000000);
pci_write_config_dword(dev_priv->device,
0x04,
temp);
}
}
/* Frees dispatch lock */
static inline void mga_dma_quiescent(drm_device_t *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
__volatile__ unsigned int *status =
(__volatile__ unsigned int *)dev_priv->status_page;
while(1) {
if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) {
break;
}
}
DRM_DEBUG("quiescent status : %x\n", MGA_READ(MGAREG_STATUS));
mga_reset_abort(dev);
while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
DRM_DEBUG("status[1] : %x last_sync_tag : %x\n", status[1],
dev_priv->last_sync_tag);
sarea_priv->dirty |= MGA_DMA_FLUSH;
clear_bit(0, &dev_priv->dispatch_lock);
}
int mga_irq_install(drm_device_t *dev, int irq)
{
@ -758,9 +780,13 @@ static int mga_flush_queue(drm_device_t *dev)
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&dev_priv->flush_queue, &entry);
for (;;) {
if (atomic_read(&dev_priv->in_flush) == 0) break;
mga_dma_schedule(dev, 0);
if (atomic_read(&dev_priv->in_flush) == 0) break;
atomic_inc(&dev->total_sleeps);
#if 0
schedule_timeout(HZ/60);
#endif
schedule();
if (signal_pending(current)) {
ret = -EINTR; /* Can't restart */
break;
@ -827,6 +853,17 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
*/
if (!ret) {
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;
if (j > 0 && j <= DRM_LOCK_SLICE) {
/* Can't take lock if we just had it and
there is contention. */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(j);
}
}
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
if (!dev->lock.hw_lock) {

View file

@ -33,7 +33,7 @@ typedef struct {
#define MGA_VERBOSE 0
#define MGA_NUM_PRIM_BUFS 4
#define MGA_NUM_PRIM_BUFS 16
/* Primary buffer versions of above -- pretty similar really.
*/
@ -45,6 +45,7 @@ drm_mga_prim_buf_t *tmp_buf = \
dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
if( (tmp_buf->max_dwords - tmp_buf->num_dwords) < length || \
tmp_buf->sec_used > (MGA_DMA_BUF_NR / 2)) { \
atomic_set(&tmp_buf->force_fire, 1); \
mga_advance_primary(dev); \
mga_dma_schedule(dev, 1); \
} \

View file

@ -116,7 +116,7 @@ extern int mga_dma_cleanup(drm_device_t *dev);
extern int mga_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern unsigned int mga_create_sync_tag(drm_mga_private_t *dev_priv);
extern unsigned int mga_create_sync_tag(drm_device_t *dev);
extern drm_buf_t *mga_freelist_get(drm_device_t *dev);
extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf);
extern int mga_advance_primary(drm_device_t *dev);

View file

@ -306,28 +306,36 @@ static void mgaEmitState( drm_mga_private_t *dev_priv )
dev_priv->WarpPipe = sarea_priv->WarpPipe;
}
if (dirty & MGA_UPLOAD_CTX)
if (dirty & MGA_UPLOAD_CTX) {
mgaEmitContext( dev_priv );
sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
}
if (dirty & MGA_UPLOAD_TEX0)
if (dirty & MGA_UPLOAD_TEX0) {
mgaG400EmitTex0( dev_priv );
sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
}
if ((dirty & MGA_UPLOAD_TEX1) && multitex)
if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
mgaG400EmitTex1( dev_priv );
sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
}
} else {
if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
mgaG200EmitPipe( dev_priv );
dev_priv->WarpPipe = sarea_priv->WarpPipe;
}
if (dirty & MGA_UPLOAD_CTX)
if (dirty & MGA_UPLOAD_CTX) {
mgaEmitContext( dev_priv );
sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
}
if (dirty & MGA_UPLOAD_TEX0)
if (dirty & MGA_UPLOAD_TEX0) {
mgaG200EmitTex( dev_priv );
sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
}
}
sarea_priv->dirty = 0;
}
/* WARNING if you change any of the state functions
@ -530,7 +538,7 @@ static inline void mga_dma_dispatch_vertex(drm_device_t *dev,
}
primary_needed += 5; /* For the dwgsync */
PRIM_OVERFLOW(dev, dev_priv, primary_needed);
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
dev_priv->last_sync_tag = mga_create_sync_tag(dev);
if(real_idx == idx) {
buf_priv->age = dev_priv->last_sync_tag;
}
@ -583,7 +591,7 @@ static inline void mga_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf)
PRIM_OVERFLOW(dev, dev_priv, 10);
PRIMGETPTR(dev_priv);
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
dev_priv->last_sync_tag = mga_create_sync_tag(dev);
buf_priv->age = dev_priv->last_sync_tag;
PRIMOUTREG( MGAREG_DMAPAD, 0);
@ -619,7 +627,7 @@ static inline void mga_dma_dispatch_clear( drm_device_t *dev, int flags,
if(primary_needed == 0) primary_needed = 35;
PRIM_OVERFLOW(dev, dev_priv, primary_needed);
PRIMGETPTR( dev_priv );
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
dev_priv->last_sync_tag = mga_create_sync_tag(dev);
for (i = 0 ; i < nbox ; i++) {
unsigned int height = pbox[i].y2 - pbox[i].y1;
@ -690,7 +698,7 @@ static inline void mga_dma_dispatch_swap( drm_device_t *dev )
PRIM_OVERFLOW(dev, dev_priv, primary_needed);
PRIMGETPTR( dev_priv );
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
dev_priv->last_sync_tag = mga_create_sync_tag(dev);
PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);