mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-09 08:38:23 +02:00
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:
parent
75d5b6bb0e
commit
95f92b7164
2 changed files with 44 additions and 55 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue