Fixed the bug which caused some lockups: UPDATE_RING_HEAD could (and was)

being called without the BM enabled. Disabled the code in
    RING_SPACE_TEST_WITH_RETURN which seems to be no longer necessary.
    Slightly enhanced ADVANCE_RING by eliminating the need to mark DMA_EOL
    in the current tail.
This commit is contained in:
Jose Fonseca 2002-06-11 15:18:04 +00:00
parent 75d5b6bb0e
commit 95f92b7164
2 changed files with 44 additions and 55 deletions

View file

@ -1071,50 +1071,26 @@ static int mach64_do_dispatch_pseudo_dma( drm_mach64_private_t *dev_priv )
#endif /* MACH64_NO_BATCH_DISPATCH */
int mach64_dma_start( drm_mach64_private_t *dev_priv )
void mach64_dma_start( drm_mach64_private_t *dev_priv )
{
#if MACH64_NO_BATCH_DISPATCH
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
if ( (MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE) )
return 0;
if ( !(MACH64_READ(MACH64_SRC_CNTL) & MACH64_SRC_BM_ENABLE) ) {
/* enable bus mastering and block 1 registers */
MACH64_WRITE( MACH64_BUS_CNTL,
( MACH64_READ(MACH64_BUS_CNTL) &
~MACH64_BUS_MASTER_DIS )
| MACH64_BUS_EXT_REG_EN );
/* enable GUI-master operation */
MACH64_WRITE( MACH64_SRC_CNTL,
MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC |
MACH64_SRC_BM_OP_SYSTEM_TO_REG );
#if MACH64_EXTRA_CHECKING
if ( (MACH64_READ(MACH64_SRC_CNTL) & MACH64_SRC_BM_ENABLE) ) {
DRM_ERROR("Call of mach64_dma_start with BM enabled!!!\n");
mach64_dump_ring( dev_priv );
}
if ( ring->head_addr < ring->start_addr ||
ring->head_addr > ring->start_addr + (ring->size - 4 * sizeof(u32)) ) {
DRM_ERROR("Bad address in BM_GUI_TABLE: 0x%08x\n", ring->head_addr);
return -EINVAL;
}
UPDATE_RING_HEAD( dev_priv, ring );
return 0;
#else
DRM_DEBUG("%s\n", __FUNCTION__);
if (list_empty(&dev_priv->dma_queue))
return 0;
dev_priv->sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT |
MACH64_UPLOAD_MISC);
if (dev_priv->driver_mode == MACH64_MODE_MMIO)
return mach64_do_dispatch_pseudo_dma( dev_priv );
else
return mach64_do_dispatch_real_dma( dev_priv );
#endif
mach64_do_wait_for_idle( dev_priv );
/* enable bus mastering and block 1 registers */
MACH64_WRITE( MACH64_BUS_CNTL,
( MACH64_READ(MACH64_BUS_CNTL) &
~MACH64_BUS_MASTER_DIS )
| MACH64_BUS_EXT_REG_EN );
/* enable GUI-master operation */
MACH64_WRITE( MACH64_SRC_CNTL,
MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC |
MACH64_SRC_BM_OP_SYSTEM_TO_REG );
}
/* IMPORTANT: This function should only be called when the engine is idle or locked up,

View file

@ -94,7 +94,7 @@ typedef struct drm_mach64_private {
/* DMA descriptor table (ring buffer) */
struct pci_pool *pool; /* DMA memory pool */
drm_mach64_descriptor_ring_t ring;
struct list_head free_list; /* Free-list head */
struct list_head placeholders; /* Free-list placeholder list */
struct list_head pending; /* Pending submission placeholder */
@ -143,9 +143,10 @@ extern int mach64_do_wait_for_idle( drm_mach64_private_t *dev_priv );
extern int mach64_wait_ring( drm_mach64_private_t *dev_priv, int n );
extern int mach64_do_release_used_buffers( drm_mach64_private_t *dev_priv );
extern void mach64_dump_engine_info( drm_mach64_private_t *dev_priv );
extern void mach64_dump_ring( drm_mach64_private_t *dev_priv );
extern int mach64_do_engine_reset( drm_mach64_private_t *dev_priv );
extern int mach64_dma_start( drm_mach64_private_t *dev_priv );
extern void mach64_dma_start( drm_mach64_private_t *dev_priv );
extern int mach64_do_dma_idle( drm_mach64_private_t *dev_priv );
extern int mach64_do_dma_flush( drm_mach64_private_t *dev_priv );
@ -456,15 +457,25 @@ extern int mach64_dma_blit( struct inode *inode, struct file *filp,
#define UPDATE_RING_HEAD( dev_priv, ring ) \
do { \
int gui_active = MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE; \
int gui_active; \
/* Start BM if it's not already on */ \
/* FIXME: This should be done with a private variable to avoid using the BUS. */ \
if ( !(MACH64_READ(MACH64_SRC_CNTL) & MACH64_SRC_BM_ENABLE) ) \
mach64_dma_start( dev_priv ); \
/* GUI_ACTIVE must be read before BM_GUI_TABLE to correctly determine the ring head */ \
gui_active = MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE; \
(ring)->head_addr = (MACH64_READ(MACH64_BM_GUI_TABLE) & 0xfffffff0); \
if ( gui_active ) { \
/* If not idle, BM_GUI_TABLE points one descriptor past the current head */ \
if ((ring)->head_addr == (ring)->start_addr) \
(ring)->head_addr += (ring)->size - 4 * sizeof(u32); \
else \
(ring)->head_addr -= 4 * sizeof(u32); \
(ring)->head_addr += (ring)->size; \
(ring)->head_addr -= 4 * sizeof(u32); \
} \
if ( MACH64_EXTRA_CHECKING && ((ring)->head_addr < (ring)->start_addr || \
(ring)->head_addr >= (ring)->start_addr + (ring)->size ) ) { \
DRM_ERROR("Bad address in BM_GUI_TABLE: 0x%08x\n", (ring)->head_addr); \
mach64_dump_ring( dev_priv ); \
} else { \
(ring)->head = ((ring)->head_addr - (ring)->start_addr) / sizeof(u32); \
if ( !gui_active && (ring)->head != (ring)->tail ) { \
/* reset descriptor table ring head */ \
@ -476,6 +487,7 @@ do { \
__FUNCTION__, \
(ring)->head_addr, (ring)->head, (ring)->tail, (ring)->space); \
} \
} \
} while (0)
static inline void
@ -523,7 +535,10 @@ do { \
/* Check for high water mark and flush if reached */
/* FIXME: right now this is needed to ensure free buffers for state emits */
#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
/* CHECKME: I've disabled this as it isn't necessary - we already wait for free buffers */
#define RING_SPACE_TEST_WITH_RETURN( dev_priv )
#define RING_SPACE_TEST_WITH_RETURN_( dev_priv ) \
do { \
struct list_head *ptr; \
int ret, queued = 0; \
@ -626,11 +641,11 @@ do { \
DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
write, tail ); \
} \
ring[(write - 2) & mask] |= cpu_to_le32( DMA_EOL ); \
wmb(); \
mach64_flush_write_combine(); \
ring[(tail - 2) & mask] &= cpu_to_le32( ~DMA_EOL ); \
wmb(); \
mach64_flush_write_combine(); \
dev_priv->ring.tail = write; \
UPDATE_RING_HEAD( dev_priv, &(dev_priv)->ring ); \
} while (0)
@ -735,11 +750,10 @@ do { \
\
OUT_RING( APERTURE_OFFSET + MACH64_BM_ADDR ); \
OUT_RING( page ); \
OUT_RING( remainder | DMA_HOLD_OFFSET ); \
OUT_RING( remainder | DMA_HOLD_OFFSET | DMA_EOL ); \
OUT_RING( 0 ); \
\
ADVANCE_RING(); \
mach64_dma_start( dev_priv ); \
} while(0)
#define DMAADVANCEHOSTDATA( dev_priv ) \
@ -807,11 +821,10 @@ do { \
\
OUT_RING( APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \
OUT_RING( page ); \
OUT_RING( remainder | DMA_HOLD_OFFSET ); \
OUT_RING( remainder | DMA_HOLD_OFFSET | DMA_EOL ); \
OUT_RING( 0 ); \
\
ADVANCE_RING(); \
mach64_dma_start( dev_priv ); \
} while(0)
#endif /* __MACH64_DRV_H__ */