From 08ef5b5e677579892a454d44a96a12dc771b56ac Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 10 Nov 2008 15:24:42 +1000 Subject: [PATCH] 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(-) 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__ */