From 08ef5b5e677579892a454d44a96a12dc771b56ac Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Mon, 10 Nov 2008 15:24:42 +1000
Subject: radeon: force all ring writes to 16-dword alignment.

---
 shared-core/radeon_cp.c  | 37 ++++++++++++++++++++++++++++++++-----
 shared-core/radeon_drv.h | 21 +++++++++------------
 2 files changed, 41 insertions(+), 17 deletions(-)

(limited to 'shared-core')

diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index 9a1e0e02..73192d03 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -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 );
+}
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index a95ab152..828ad3f9 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -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__ */
-- 
cgit v1.2.3