summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/mga_drv.h2
-rw-r--r--shared/mga_state.c1
-rw-r--r--shared/radeon_cp.c22
-rw-r--r--shared/radeon_drv.h5
-rw-r--r--shared/radeon_state.c20
5 files changed, 42 insertions, 8 deletions
diff --git a/shared/mga_drv.h b/shared/mga_drv.h
index 51bc706e9..0845009bb 100644
--- a/shared/mga_drv.h
+++ b/shared/mga_drv.h
@@ -38,7 +38,7 @@ typedef struct drm_mga_primary_buffer {
u32 tail;
int space;
- int wrapped;
+ volatile long wrapped;
volatile u32 *status;
diff --git a/shared/mga_state.c b/shared/mga_state.c
index adf67de36..734432d59 100644
--- a/shared/mga_state.c
+++ b/shared/mga_state.c
@@ -37,7 +37,6 @@
#include "drm.h"
#include "mga_drm.h"
#include "mga_drv.h"
-#include "drm.h"
/* ================================================================
diff --git a/shared/radeon_cp.c b/shared/radeon_cp.c
index d56a90023..01069e498 100644
--- a/shared/radeon_cp.c
+++ b/shared/radeon_cp.c
@@ -925,6 +925,24 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+ /* Writeback doesn't seem to work everywhere, test it first */
+ DRM_WRITE32( &dev_priv->scratch[1], 0 );
+ RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
+
+ for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
+ if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef )
+ break;
+ DRM_UDELAY( 1 );
+ }
+
+ if ( tmp < dev_priv->usec_timeout ) {
+ dev_priv->writeback_works = 1;
+ DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
+ } else {
+ dev_priv->writeback_works = 0;
+ DRM_DEBUG( "writeback test failed\n" );
+ }
+
dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
RADEON_WRITE( RADEON_LAST_FRAME_REG,
dev_priv->sarea_priv->last_frame );
@@ -1456,8 +1474,8 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
start = dev_priv->last_buf;
for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
- u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
-
+ u32 done_age = GET_SCRATCH( 1 );
+ DRM_DEBUG("done_age = %d\n",done_age);
for ( i = start ; i < dma->buf_count ; i++ ) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
diff --git a/shared/radeon_drv.h b/shared/radeon_drv.h
index 57cd5f4fd..7c341b39e 100644
--- a/shared/radeon_drv.h
+++ b/shared/radeon_drv.h
@@ -76,6 +76,7 @@ typedef struct drm_radeon_private {
drm_radeon_freelist_t *tail;
int last_buf;
volatile u32 *scratch;
+ int writeback_works;
int usec_timeout;
@@ -233,6 +234,10 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS );
#define RADEON_SCRATCH_UMSK 0x0770
#define RADEON_SCRATCH_ADDR 0x0774
+#define GET_SCRATCH( x ) (dev_priv->writeback_works \
+ ? DRM_READ32( &dev_priv->scratch[(x)] ) \
+ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+
#define RADEON_HOST_PATH_CNTL 0x0130
# define RADEON_HDP_SOFT_RESET (1 << 26)
# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
diff --git a/shared/radeon_state.c b/shared/radeon_state.c
index 7b2dbdfbd..7f84e739a 100644
--- a/shared/radeon_state.c
+++ b/shared/radeon_state.c
@@ -1936,6 +1936,19 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
if ( i < cmdbuf->nbox ) {
if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
return DRM_ERR(EFAULT);
+ /* FIXME The second and subsequent times round this loop, send a
+ * WAIT_UNTIL_3D_IDLE before calling emit_clip_rect(). This
+ * fixes a lockup on fast machines when sending several
+ * cliprects with a cmdbuf, as when waving a 2D window over
+ * a 3D window. Something in the commands from user space
+ * seems to hang the card when they're sent several times
+ * in a row. That would be the correct place to fix it but
+ * this works around it until I can figure that out - Tim Smith */
+ if ( i ) {
+ BEGIN_RING( 2 );
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+ }
radeon_emit_clip_rect( dev_priv, &box );
}
@@ -1944,7 +1957,6 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
ADVANCE_RING();
} while ( ++i < cmdbuf->nbox );
-
if (cmdbuf->nbox == 1)
cmdbuf->nbox = 0;
@@ -2107,14 +2119,14 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
break;
case RADEON_PARAM_LAST_FRAME:
dev_priv->stats.last_frame_reads++;
- value = DRM_READ32(&dev_priv->scratch[0]);
+ value = GET_SCRATCH( 0 );
break;
case RADEON_PARAM_LAST_DISPATCH:
- value = DRM_READ32(&dev_priv->scratch[1]);
+ value = GET_SCRATCH( 1 );
break;
case RADEON_PARAM_LAST_CLEAR:
dev_priv->stats.last_clear_reads++;
- value = DRM_READ32(&dev_priv->scratch[2]);
+ value = GET_SCRATCH( 2 );
break;
default:
return DRM_ERR(EINVAL);