summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2002-07-31 08:04:01 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2002-07-31 08:04:01 +0000
commit6b4dd1a7a444945be81d9b81c22ef593236ae461 (patch)
treef427818e7107183cb253f67f7471264009719ff0
parent99f4d6e174d0a531f3a162a37b40d7ad459d3c96 (diff)
downloaddrm-6b4dd1a7a444945be81d9b81c22ef593236ae461.tar.gz
Put back in-kernel udelay (until better solution)
-rw-r--r--shared-core/radeon_cp.c74
-rw-r--r--shared/radeon_cp.c74
2 files changed, 116 insertions, 32 deletions
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index 92f7678b..d56a9002 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -605,6 +605,8 @@ static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
u32 tmp;
int i;
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
tmp |= RADEON_RB2D_DC_FLUSH_ALL;
RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
@@ -629,6 +631,8 @@ static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
{
int i;
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
& RADEON_RBBM_FIFOCNT_MASK );
@@ -647,6 +651,8 @@ static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
{
int i, ret;
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
ret = radeon_do_wait_for_fifo( dev_priv, 64 );
if ( ret ) return ret;
@@ -1425,6 +1431,14 @@ int radeon_fullscreen( DRM_IOCTL_ARGS )
* completed rendering.
*
* KW: It's also a good way to find free buffers quickly.
+ *
+ * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
+ * sleep. However, bugs in older versions of radeon_accel.c mean that
+ * we essentially have to do this, else old clients will break.
+ *
+ * However, it does leave open a potential deadlock where all the
+ * buffers are held by other clients, which can't release them because
+ * they can't get the lock.
*/
drm_buf_t *radeon_freelist_get( drm_device_t *dev )
@@ -1435,41 +1449,70 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
drm_buf_t *buf;
int i, t;
int start;
- u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
-
- dev_priv->stats.requested_bufs++;
- if (done_age == dev_priv->sarea_priv->last_dispatch)
- dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE;
if ( ++dev_priv->last_buf >= dma->buf_count )
dev_priv->last_buf = 0;
start = dev_priv->last_buf;
-
-/* printk("start %d count %d\n", start, dma->buf_count); */
for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
- DRM_DEBUG("done_age = %d\n",done_age);
+ u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
+
for ( i = start ; i < dma->buf_count ; i++ ) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
if ( buf->pid == 0 || (buf->pending &&
buf_priv->age <= done_age) ) {
+ dev_priv->stats.requested_bufs++;
buf->pending = 0;
-/* if (t) printk("wait: %d\n", t); */
return buf;
}
start = 0;
}
- dev_priv->stats.freelist_loops++;
- if (t) DRM_UDELAY( 1 );
- done_age = DRM_READ32(&dev_priv->scratch[1]);
+
+ if (t) {
+ DRM_UDELAY( 1 );
+ dev_priv->stats.freelist_loops++;
+ }
}
- dev_priv->stats.freelist_timeouts++;
DRM_ERROR( "returning NULL!\n" );
return NULL;
}
+#if 0
+drm_buf_t *radeon_freelist_get( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_buf_t *buf;
+ int i, t;
+ int start;
+ u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
+
+ if ( ++dev_priv->last_buf >= dma->buf_count )
+ dev_priv->last_buf = 0;
+
+ start = dev_priv->last_buf;
+ dev_priv->stats.freelist_loops++;
+
+ for ( t = 0 ; t < 2 ; t++ ) {
+ for ( i = start ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if ( buf->pid == 0 || (buf->pending &&
+ buf_priv->age <= done_age) ) {
+ dev_priv->stats.requested_bufs++;
+ buf->pending = 0;
+ return buf;
+ }
+ }
+ start = 0;
+ }
+
+ return NULL;
+}
+#endif
void radeon_freelist_reset( drm_device_t *dev )
{
@@ -1496,7 +1539,6 @@ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
int i;
u32 last_head = GET_RING_HEAD(ring);
-
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
u32 head = GET_RING_HEAD(ring);
@@ -1506,7 +1548,7 @@ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
if ( ring->space > n )
return 0;
- dev_priv->stats.boxes |= RADEON_BOX_RING_FULL;
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
if (head != last_head)
i = 0;
@@ -1530,7 +1572,7 @@ static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
for ( i = d->granted_count ; i < d->request_count ; i++ ) {
buf = radeon_freelist_get( dev );
- if ( !buf ) return DRM_ERR(EAGAIN);
+ if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
buf->pid = DRM_CURRENTPID;
diff --git a/shared/radeon_cp.c b/shared/radeon_cp.c
index 92f7678b..d56a9002 100644
--- a/shared/radeon_cp.c
+++ b/shared/radeon_cp.c
@@ -605,6 +605,8 @@ static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
u32 tmp;
int i;
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
tmp |= RADEON_RB2D_DC_FLUSH_ALL;
RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
@@ -629,6 +631,8 @@ static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
{
int i;
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
& RADEON_RBBM_FIFOCNT_MASK );
@@ -647,6 +651,8 @@ static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
{
int i, ret;
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
ret = radeon_do_wait_for_fifo( dev_priv, 64 );
if ( ret ) return ret;
@@ -1425,6 +1431,14 @@ int radeon_fullscreen( DRM_IOCTL_ARGS )
* completed rendering.
*
* KW: It's also a good way to find free buffers quickly.
+ *
+ * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
+ * sleep. However, bugs in older versions of radeon_accel.c mean that
+ * we essentially have to do this, else old clients will break.
+ *
+ * However, it does leave open a potential deadlock where all the
+ * buffers are held by other clients, which can't release them because
+ * they can't get the lock.
*/
drm_buf_t *radeon_freelist_get( drm_device_t *dev )
@@ -1435,41 +1449,70 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
drm_buf_t *buf;
int i, t;
int start;
- u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
-
- dev_priv->stats.requested_bufs++;
- if (done_age == dev_priv->sarea_priv->last_dispatch)
- dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE;
if ( ++dev_priv->last_buf >= dma->buf_count )
dev_priv->last_buf = 0;
start = dev_priv->last_buf;
-
-/* printk("start %d count %d\n", start, dma->buf_count); */
for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
- DRM_DEBUG("done_age = %d\n",done_age);
+ u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
+
for ( i = start ; i < dma->buf_count ; i++ ) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
if ( buf->pid == 0 || (buf->pending &&
buf_priv->age <= done_age) ) {
+ dev_priv->stats.requested_bufs++;
buf->pending = 0;
-/* if (t) printk("wait: %d\n", t); */
return buf;
}
start = 0;
}
- dev_priv->stats.freelist_loops++;
- if (t) DRM_UDELAY( 1 );
- done_age = DRM_READ32(&dev_priv->scratch[1]);
+
+ if (t) {
+ DRM_UDELAY( 1 );
+ dev_priv->stats.freelist_loops++;
+ }
}
- dev_priv->stats.freelist_timeouts++;
DRM_ERROR( "returning NULL!\n" );
return NULL;
}
+#if 0
+drm_buf_t *radeon_freelist_get( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_buf_t *buf;
+ int i, t;
+ int start;
+ u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
+
+ if ( ++dev_priv->last_buf >= dma->buf_count )
+ dev_priv->last_buf = 0;
+
+ start = dev_priv->last_buf;
+ dev_priv->stats.freelist_loops++;
+
+ for ( t = 0 ; t < 2 ; t++ ) {
+ for ( i = start ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if ( buf->pid == 0 || (buf->pending &&
+ buf_priv->age <= done_age) ) {
+ dev_priv->stats.requested_bufs++;
+ buf->pending = 0;
+ return buf;
+ }
+ }
+ start = 0;
+ }
+
+ return NULL;
+}
+#endif
void radeon_freelist_reset( drm_device_t *dev )
{
@@ -1496,7 +1539,6 @@ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
int i;
u32 last_head = GET_RING_HEAD(ring);
-
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
u32 head = GET_RING_HEAD(ring);
@@ -1506,7 +1548,7 @@ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
if ( ring->space > n )
return 0;
- dev_priv->stats.boxes |= RADEON_BOX_RING_FULL;
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
if (head != last_head)
i = 0;
@@ -1530,7 +1572,7 @@ static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
for ( i = d->granted_count ; i < d->request_count ; i++ ) {
buf = radeon_freelist_get( dev );
- if ( !buf ) return DRM_ERR(EAGAIN);
+ if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
buf->pid = DRM_CURRENTPID;