diff options
author | Gareth Hughes <gareth@users.sourceforge.net> | 2000-10-15 02:32:37 +0000 |
---|---|---|
committer | Gareth Hughes <gareth@users.sourceforge.net> | 2000-10-15 02:32:37 +0000 |
commit | 3c8b613ae28fe3ef5c8e82ea0ca6b73480f411a5 (patch) | |
tree | 90dc4bb718cd73d3fcefa2e72646ae00a6fd5a3e | |
parent | ce71d0abb92783b8b6077f42cf261842e06e17f8 (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.c | 2 | ||||
-rw-r--r-- | linux/r128_cce.c | 190 | ||||
-rw-r--r-- | linux/r128_drm.h | 1 | ||||
-rw-r--r-- | linux/r128_drv.c | 2 | ||||
-rw-r--r-- | linux/r128_drv.h | 2 | ||||
-rw-r--r-- | linux/r128_state.c | 43 |
6 files changed, 124 insertions, 116 deletions
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index bf7cffcb..81909f94 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 a58277bb..e95a8471 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 c67aa8d6..fb7b53b5 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 bf7cffcb..81909f94 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 69240eed..a4110442 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 1e080840..03c2da67 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; |