summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth Hughes <gareth@users.sourceforge.net>2000-10-15 02:32:37 +0000
committerGareth Hughes <gareth@users.sourceforge.net>2000-10-15 02:32:37 +0000
commit3c8b613ae28fe3ef5c8e82ea0ca6b73480f411a5 (patch)
tree90dc4bb718cd73d3fcefa2e72646ae00a6fd5a3e
parentce71d0abb92783b8b6077f42cf261842e06e17f8 (diff)
Fix last of lockups. Stopping the CCE was failing when the engine was very
busy, and this wasn't being handled gracefully. Works great now.
-rw-r--r--linux-core/r128_drv.c2
-rw-r--r--linux/r128_cce.c190
-rw-r--r--linux/r128_drm.h1
-rw-r--r--linux/r128_drv.c2
-rw-r--r--linux/r128_drv.h2
-rw-r--r--linux/r128_state.c43
6 files changed, 124 insertions, 116 deletions
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c
index bf7cffcb8..81909f949 100644
--- a/linux-core/r128_drv.c
+++ b/linux-core/r128_drv.c
@@ -35,7 +35,7 @@
#define R128_NAME "r128"
#define R128_DESC "ATI Rage 128"
-#define R128_DATE "20001010"
+#define R128_DATE "20001015"
#define R128_MAJOR 1
#define R128_MINOR 1
#define R128_PATCHLEVEL 0
diff --git a/linux/r128_cce.c b/linux/r128_cce.c
index a58277bb2..e95a84712 100644
--- a/linux/r128_cce.c
+++ b/linux/r128_cce.c
@@ -154,6 +154,7 @@ static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv )
udelay( 1 );
}
+ DRM_DEBUG( "%s failed!\n", __FUNCTION__ );
return -EBUSY;
}
@@ -166,6 +167,8 @@ static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
if ( slots >= entries ) return 0;
udelay( 1 );
}
+
+ DRM_DEBUG( "%s failed!\n", __FUNCTION__ );
return -EBUSY;
}
@@ -183,6 +186,8 @@ static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
}
udelay( 1 );
}
+
+ DRM_DEBUG( "%s failed!\n", __FUNCTION__ );
return -EBUSY;
}
@@ -238,6 +243,7 @@ static int r128_do_cce_idle( drm_r128_private_t *dev_priv )
udelay( 1 );
}
+ DRM_DEBUG( "%s failed!\n", __FUNCTION__ );
return -EBUSY;
}
@@ -251,6 +257,8 @@ static void r128_do_cce_start( drm_r128_private_t *dev_priv )
dev_priv->cce_mode | dev_priv->ring.size_l2qw );
R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
+
+ dev_priv->cce_running = 1;
}
/* Reset the Concurrent Command Engine. This will not flush any pending
@@ -273,9 +281,11 @@ static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
{
R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
R128_WRITE( R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4 );
+
+ dev_priv->cce_running = 0;
}
-/* Reset the engine, and the CCE if it is currently running.
+/* Reset the engine. This will stop the CCE if it is running.
*/
static int r128_do_engine_reset( drm_device_t *dev )
{
@@ -307,10 +317,8 @@ static int r128_do_engine_reset( drm_device_t *dev )
/* Reset the CCE ring */
r128_do_cce_reset( dev_priv );
- if ( dev_priv->cce_running ) {
- /* Start the CCE again */
- r128_do_cce_start( dev_priv );
- }
+ /* The CCE is no longer running after an engine reset */
+ dev_priv->cce_running = 0;
/* Reset any pending vertex, indirect buffers */
r128_freelist_reset( dev );
@@ -320,7 +328,7 @@ static int r128_do_engine_reset( drm_device_t *dev )
static void r128_cce_init_ring_buffer( drm_device_t *dev )
{
- drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_private_t *dev_priv = dev->dev_private;
u32 ring_start;
u32 tmp;
@@ -555,7 +563,7 @@ int r128_cce_start( struct inode *inode, struct file *filp,
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
dev->lock.pid != current->pid ) {
- DRM_ERROR( "r128_cce_start called without lock held\n" );
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
return -EINVAL;
}
if ( !dev_priv )
@@ -566,7 +574,6 @@ int r128_cce_start( struct inode *inode, struct file *filp,
r128_do_cce_start( dev_priv );
- dev_priv->cce_running = 1;
return 0;
}
@@ -576,10 +583,11 @@ int r128_cce_stop( struct inode *inode, struct file *filp,
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_r128_private_t *dev_priv = dev->dev_private;
+ int ret;
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
dev->lock.pid != current->pid ) {
- DRM_ERROR( "r128_cce_stop called without lock held\n" );
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
return -EINVAL;
}
if ( !dev_priv )
@@ -588,15 +596,23 @@ int r128_cce_stop( struct inode *inode, struct file *filp,
if ( !dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 )
return 0;
- /* Flush any pending CCE commands, then turn off the engine */
+ /* Flush any pending CCE commands. This ensures any outstanding
+ * commands are exectuted by the engine before we turn it off.
+ */
r128_do_cce_flush( dev_priv );
- r128_do_cce_idle( dev_priv );
- r128_do_cce_stop( dev_priv );
- /* Mark the CCE as off so it is not reset */
- dev_priv->cce_running = 0;
+ /* If we fail to make the engine go idle, we return an error
+ * code so that the DRM ioctl wrapper can try again.
+ */
+ ret = r128_do_cce_idle( dev_priv );
+ if ( ret < 0 ) return ret;
+
+ /* Finally, if we've managed to make the engine go idle, we
+ * can turn off the CCE.
+ */
+ r128_do_cce_stop( dev_priv );
- /* Reset the engine, but not the CCE */
+ /* Reset the engine */
r128_do_engine_reset( dev );
return 0;
@@ -613,7 +629,7 @@ int r128_cce_reset( struct inode *inode, struct file *filp,
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
dev->lock.pid != current->pid ) {
- DRM_ERROR( "r128_cce_reset called without lock held\n" );
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
return -EINVAL;
}
if ( !dev_priv )
@@ -624,8 +640,9 @@ int r128_cce_reset( struct inode *inode, struct file *filp,
r128_do_cce_reset( dev_priv );
- /* The ring is no longer in use */
+ /* The CCE is no longer running after an engine reset */
dev_priv->cce_running = 0;
+
return 0;
}
@@ -638,7 +655,7 @@ int r128_cce_idle( struct inode *inode, struct file *filp,
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
dev->lock.pid != current->pid ) {
- DRM_ERROR( "r128_cce_idle called without lock held\n" );
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
return -EINVAL;
}
@@ -654,7 +671,7 @@ int r128_engine_reset( struct inode *inode, struct file *filp,
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
dev->lock.pid != current->pid ) {
- DRM_ERROR( "r128_engine_reset called without lock held\n" );
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
return -EINVAL;
}
@@ -665,18 +682,56 @@ int r128_engine_reset( struct inode *inode, struct file *filp,
/* ================================================================
* Freelist management
*/
+#if 0
+#define R128_BUFFER_USED 0xffffffff
+#define R128_BUFFER_FREE 0
-void r128_freelist_reset( drm_device_t *dev )
+static int r128_freelist_init( drm_device_t *dev )
{
drm_device_dma_t *dma = dev->dma;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_buf_t *buf;
+ drm_r128_buf_priv_t *buf_priv;
+ drm_r128_freelist_t *entry;
int i;
+ dev_priv->head = drm_alloc( sizeof(drm_r128_freelist_t),
+ DRM_MEM_DRIVER );
+ if ( dev_priv->head == NULL )
+ return -ENOMEM;
+
+ memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) );
+ dev_priv->head->age = R128_BUFFER_USED;
+
for ( i = 0 ; i < dma->buf_count ; i++ ) {
- drm_buf_t *buf = dma->buflist[i];
- drm_r128_buf_priv_t *buf_priv = buf->dev_private;
- buf_priv->age = 0;
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+
+ entry = drm_alloc( sizeof(drm_r128_freelist_t),
+ DRM_MEM_DRIVER );
+ if ( !entry ) return -ENOMEM;
+
+ entry->age = R128_BUFFER_FREE;
+ entry->buf = buf;
+ entry->prev = dev_priv->head;
+ entry->next = dev_priv->head->next;
+ if ( !entry->next )
+ dev_priv->tail = entry;
+
+ buf_priv->discard = 0;
+ buf_priv->dispatched = 0;
+ buf_priv->list_entry = entry;
+
+ dev_priv->head->next = entry;
+
+ if ( dev_priv->head->next )
+ dev_priv->head->next->prev = entry;
}
+
+ return 0;
+
}
+#endif
drm_buf_t *r128_freelist_get( drm_device_t *dev )
{
@@ -711,10 +766,22 @@ drm_buf_t *r128_freelist_get( drm_device_t *dev )
udelay( 1 );
}
- r128_status( dev );
+ DRM_ERROR( "%s: returning NULL!\n", __FUNCTION__ );
return NULL;
}
+void r128_freelist_reset( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+ buf_priv->age = 0;
+ }
+}
+
/* ================================================================
* CCE packet submission
@@ -722,11 +789,11 @@ drm_buf_t *r128_freelist_get( drm_device_t *dev )
int r128_wait_ring( drm_r128_private_t *dev_priv, int n )
{
- drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+ drm_r128_ring_buffer_t *ring = &dev_priv->ring;
int i;
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- ring->space = *ring->head - dev_priv->ring.tail;
+ ring->space = *ring->head - dev_priv->ring.tail;
if ( ring->space <= 0 )
ring->space += ring->size;
@@ -741,10 +808,10 @@ int r128_wait_ring( drm_r128_private_t *dev_priv, int n )
void r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
{
- drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+ drm_r128_ring_buffer_t *ring = &dev_priv->ring;
- ring->space = *ring->head - dev_priv->ring.tail;
- if ( ring->space <= 0 )
+ ring->space = *ring->head - dev_priv->ring.tail;
+ if ( ring->space <= 0 )
ring->space += ring->size;
}
@@ -1088,68 +1155,3 @@ static int r128_send_vertbufs( drm_device_t *dev, drm_r128_vertex_t *v )
return 0;
}
#endif
-
-#if 0
-int r128_dma( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_r128_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- int retcode = 0;
- drm_dma_t d;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
-
- if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
- dev->lock.pid != current->pid ) {
- DRM_ERROR( "r128_dma called without lock held\n" );
- return -EINVAL;
- }
- if ( !dev_priv || dev_priv->is_pci ) {
- DRM_ERROR( "r128_dma called with a PCI card\n" );
- return -EINVAL;
- }
-
- if ( copy_from_user( &v, (drm_r128_vertex_t *)arg, sizeof(v) ) )
- return -EFAULT;
- DRM_DEBUG( "%d: %d send, %d req\n",
- current->pid, v.send_count, v.request_count );
-
-#if 0
- if ( d.send_count < 0 || d.send_count > dma->buf_count ) {
- DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
- current->pid, v.send_count, dma->buf_count);
- return -EINVAL;
- }
-#else
- if ( d.send_count != 0 ) {
- DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
- current->pid, d.send_count );
- return -EINVAL;
- }
-#endif
- if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
- DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
- current->pid, d.request_count, dma->buf_count );
- return -EINVAL;
- }
-#if 0
- if ( v.send_count ) {
- retcode = r128_send_vertbufs( dev, &v );
- }
-#endif
- v.granted_count = 0;
-
- if ( /* !retcode && */ d.request_count ) {
- retcode = r128_get_dma_buffers( dev, &d );
- }
-
- DRM_DEBUG( "%d returning, granted = %d\n",
- current->pid, d.granted_count );
- if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
- return -EFAULT;
-
- return retcode;
-}
-#endif
diff --git a/linux/r128_drm.h b/linux/r128_drm.h
index c67aa8d67..fb7b53b51 100644
--- a/linux/r128_drm.h
+++ b/linux/r128_drm.h
@@ -50,6 +50,7 @@
#define R128_UPLOAD_WINDOW 0x100
#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */
#define R128_REQUIRE_QUIESCENCE 0x400
+#define R128_UPLOAD_ALL 0x7ff
#define R128_FRONT 0x1
#define R128_BACK 0x2
diff --git a/linux/r128_drv.c b/linux/r128_drv.c
index bf7cffcb8..81909f949 100644
--- a/linux/r128_drv.c
+++ b/linux/r128_drv.c
@@ -35,7 +35,7 @@
#define R128_NAME "r128"
#define R128_DESC "ATI Rage 128"
-#define R128_DATE "20001010"
+#define R128_DATE "20001015"
#define R128_MAJOR 1
#define R128_MINOR 1
#define R128_PATCHLEVEL 0
diff --git a/linux/r128_drv.h b/linux/r128_drv.h
index 69240eedd..a41104422 100644
--- a/linux/r128_drv.h
+++ b/linux/r128_drv.h
@@ -96,7 +96,7 @@ typedef struct drm_r128_buf_priv {
u32 age;
int discard;
int dispatched;
- drm_r128_freelist_t *my_freelist;
+ drm_r128_freelist_t *list_entry;
} drm_r128_buf_priv_t;
/* r128_drv.c */
diff --git a/linux/r128_state.c b/linux/r128_state.c
index 1e0808400..03c2da679 100644
--- a/linux/r128_state.c
+++ b/linux/r128_state.c
@@ -267,6 +267,10 @@ static inline void r128_emit_state( drm_r128_private_t *dev_priv )
/* Turn off the texture cache flushing */
sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
+
+ sarea_priv->dirty &= ~(R128_UPLOAD_TEX0IMAGES |
+ R128_UPLOAD_TEX1IMAGES |
+ R128_REQUIRE_QUIESCENCE);
}
@@ -276,18 +280,18 @@ static inline void r128_emit_state( drm_r128_private_t *dev_priv )
static void r128_print_dirty( const char *msg, unsigned int flags )
{
- DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
- msg,
- flags,
- (flags & R128_UPLOAD_CORE) ? "core, " : "",
- (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
- (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
- (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
- (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
- (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
- (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
- (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
- (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
+ DRM_DEBUG( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & R128_UPLOAD_CORE) ? "core, " : "",
+ (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
+ (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
+ (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
+ (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
+ (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
+ (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
+ (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+ (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
}
static void r128_cce_dispatch_clear( drm_device_t *dev,
@@ -510,14 +514,15 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev,
DRM_DEBUG( "vertex buffer index = %d\n", index );
DRM_DEBUG( "vertex buffer offset = 0x%x\n", offset );
- DRM_DEBUG( "vertex buffer size = %d bytes\n", size );
+ DRM_DEBUG( "vertex buffer size = %d vertices, %d bytes\n",
+ size, buf->used );
DRM_DEBUG( "vertex size = %d\n", vertsize );
DRM_DEBUG( "vertex format = 0x%x\n", format );
r128_update_ring_snapshot( dev_priv );
if ( 0 )
- r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
+ r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST;
@@ -588,7 +593,6 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev,
static void r128_get_vertex_buffer( drm_device_t *dev, drm_r128_vertex_t *v )
{
drm_buf_t *buf;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
buf = r128_freelist_get( dev );
if ( !buf ) return;
@@ -671,7 +675,6 @@ int r128_cce_vertex( struct inode *inode, struct file *filp,
drm_buf_t *buf;
drm_r128_buf_priv_t *buf_priv;
drm_r128_vertex_t vertex;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
dev->lock.pid != current->pid ) {
@@ -686,8 +689,9 @@ int r128_cce_vertex( struct inode *inode, struct file *filp,
if ( copy_from_user( &vertex, (drm_r128_vertex_t *)arg,
sizeof(vertex) ) )
return -EFAULT;
- DRM_DEBUG( "%d: index=%d used=%d flags=%s%s%s\n",
- current->pid, vertex.index, vertex.used,
+
+ DRM_DEBUG( "%s: pid=%d index=%d used=%d flags=%s%s%s\n",
+ __FUNCTION__, current->pid, vertex.index, vertex.used,
( vertex.send ) ? "S" : ".",
( vertex.discard ) ? "D" : ".",
( vertex.request ) ? "R" : "." );
@@ -727,7 +731,8 @@ int r128_cce_vertex( struct inode *inode, struct file *filp,
r128_get_vertex_buffer( dev, &vertex );
}
- DRM_DEBUG( "%d: returning, index=%d\n", current->pid, vertex.index );
+ DRM_DEBUG( "%s: returning, pid=%d index=%d\n",
+ __FUNCTION__, current->pid, vertex.index );
if ( copy_to_user( (drm_r128_vertex_t *)arg, &vertex,
sizeof(vertex) ) )
return -EFAULT;