radeon: force all ring writes to 16-dword alignment.
authorDave Airlie <airlied@redhat.com>
Mon, 10 Nov 2008 05:24:42 +0000 (15:24 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 10 Nov 2008 05:24:42 +0000 (15:24 +1000)
shared-core/radeon_cp.c
shared-core/radeon_drv.h

index 9a1e0e0..73192d0 100644 (file)
@@ -1313,9 +1313,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
        dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
        dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8);
 
-       dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
-       dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16);
-
+       dev_priv->ring.fetch_size_l2ow = 2;
        dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
 
        dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
@@ -2513,8 +2511,7 @@ int radeon_modeset_cp_init(struct drm_device *dev)
        dev_priv->ring.size_l2qw = drm_order(dev_priv->ring.size / 8);
        dev_priv->ring.rptr_update = 4096;
        dev_priv->ring.rptr_update_l2qw = drm_order(4096 / 8);
-       dev_priv->ring.fetch_size = 32;
-       dev_priv->ring.fetch_size_l2ow = drm_order(32 / 16);
+       dev_priv->ring.fetch_size_l2ow = 2; /* do what tcore does */
        dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
        dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
 
@@ -2841,3 +2838,33 @@ void radeon_gart_flush(struct drm_device *dev)
        }
        
 }
+
+void radeon_commit_ring(drm_radeon_private_t *dev_priv)
+{
+       int i;
+       u32 *ring;
+       int tail_aligned;
+
+       /* check if the ring is padded out to 16-dword alignment */
+       
+       tail_aligned = dev_priv->ring.tail & 0xf;
+       if (tail_aligned) {
+               int num_p2 = 16 - tail_aligned;
+
+               ring = dev_priv->ring.start;
+               /* pad with some CP_PACKET2 */
+               for (i = 0; i < num_p2; i++)
+                       ring[dev_priv->ring.tail + i] = CP_PACKET2();
+       
+               dev_priv->ring.tail += i;
+
+               dev_priv->ring.space -= num_p2 * sizeof(u32);
+       }
+               
+       DRM_MEMORYBARRIER();
+       GET_RING_HEAD( dev_priv );
+
+       RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail );
+       /* read from PCI bus to ensure correct posting */
+       RADEON_READ( RADEON_CP_RB_RPTR );
+}
index a95ab15..828ad3f 100644 (file)
@@ -219,7 +219,6 @@ typedef struct drm_radeon_ring_buffer {
        int rptr_update; /* Double Words */
        int rptr_update_l2qw; /* log2 Quad Words */
 
-       int fetch_size; /* Double Words */
        int fetch_size_l2ow; /* log2 Oct Words */
 
        u32 tail;
@@ -1515,15 +1514,16 @@ do {                                                                    \
 
 #define RADEON_VERBOSE 0
 
-#define RING_LOCALS    int write, _nr; unsigned int mask; u32 *ring;
+#define RING_LOCALS    int write, _nr, _align_nr; unsigned int mask; u32 *ring;
 
 #define BEGIN_RING( n ) do {                                           \
        if ( RADEON_VERBOSE ) {                                         \
                DRM_INFO( "BEGIN_RING( %d )\n", (n));                   \
        }                                                               \
-       if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {              \
+       _align_nr = (n + 0xf) & ~0xf;                                   \
+       if (dev_priv->ring.space <= (_align_nr * sizeof(u32))) {        \
                COMMIT_RING();                                          \
-               radeon_wait_ring( dev_priv, (n) * sizeof(u32) );        \
+               radeon_wait_ring(dev_priv, _align_nr * sizeof(u32));    \
        }                                                               \
        _nr = n; dev_priv->ring.space -= (n) * sizeof(u32);             \
        ring = dev_priv->ring.start;                                    \
@@ -1540,19 +1540,14 @@ do {                                                                    \
                DRM_ERROR(                                              \
                        "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",        \
                        ((dev_priv->ring.tail + _nr) & mask),           \
-                       write, __LINE__);                                               \
+                       write, __LINE__);                               \
        } else                                                          \
                dev_priv->ring.tail = write;                            \
 } while (0)
 
 #define COMMIT_RING() do {                                             \
-       /* Flush writes to ring */                                      \
-       DRM_MEMORYBARRIER();                                            \
-       GET_RING_HEAD( dev_priv );                                      \
-       RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail );         \
-       /* read from PCI bus to ensure correct posting */               \
-       RADEON_READ( RADEON_CP_RB_RPTR );                               \
-} while (0)
+               radeon_commit_ring(dev_priv);                           \
+       } while(0)
 
 #define OUT_RING( x ) do {                                             \
        if ( RADEON_VERBOSE ) {                                         \
@@ -1731,6 +1726,8 @@ extern void radeon_gem_proc_cleanup(struct drm_minor *minor);
 #define MARK_CHECK_OFFSET      2
 #define MARK_CHECK_SCISSOR     3
 
+extern void radeon_commit_ring(drm_radeon_private_t *dev_priv);
+
 extern int r300_check_range(unsigned reg, int count);
 extern int r300_get_reg_flags(unsigned reg);
 #endif                         /* __RADEON_DRV_H__ */