diff options
author | Eric Anholt <anholt@freebsd.org> | 2005-01-20 16:22:04 +0000 |
---|---|---|
committer | Eric Anholt <anholt@freebsd.org> | 2005-01-20 16:22:04 +0000 |
commit | 13c6b2f0b6c464ce11f6c332b2fa1a529bdbab01 (patch) | |
tree | 7be05625e56e69800350b1a47fa3734bb2e73736 /hw/kdrive/ati | |
parent | dbe45c71590ac319250d04a2bf37ec07cd79e42a (diff) |
Add a set of macros for dealing with the repeated code to wait for a while
reading a register/attempting DMA. Now it'll wait for a certain number
of seconds rather than a certain number of times through the loop
before deciding that it's timed out and resetting the hardware. Also,
add more timeout handling, and reset the draw state after resetting the
engine.
Diffstat (limited to 'hw/kdrive/ati')
-rw-r--r-- | hw/kdrive/ati/ati_dma.c | 83 | ||||
-rw-r--r-- | hw/kdrive/ati/ati_dma.h | 21 | ||||
-rw-r--r-- | hw/kdrive/ati/ati_dri.c | 9 |
3 files changed, 79 insertions, 34 deletions
diff --git a/hw/kdrive/ati/ati_dma.c b/hw/kdrive/ati/ati_dma.c index 975707668..1acb8e544 100644 --- a/hw/kdrive/ati/ati_dma.c +++ b/hw/kdrive/ati/ati_dma.c @@ -21,6 +21,8 @@ */ /* $Header$ */ +#include <sys/time.h> + #include "ati.h" #include "ati_reg.h" #include "ati_dma.h" @@ -115,15 +117,15 @@ ATIFlushPixelCache(ATIScreenInfo *atis) { ATICardInfo *atic = atis->atic; char *mmio = atic->reg_base; - int tries; CARD32 temp; + TIMEOUT_LOCALS; if (atic->is_radeon) { temp = MMIO_IN32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT); temp |= RADEON_RB2D_DC_FLUSH_ALL; MMIO_OUT32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT, temp); - for (tries = 1000000; tries != 0; tries--) { + WHILE_NOT_TIMEOUT(.2) { if ((MMIO_IN32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY) == 0) break; @@ -133,13 +135,13 @@ ATIFlushPixelCache(ATIScreenInfo *atis) temp |= R128_PC_FLUSH_ALL; MMIO_OUT32(mmio, R128_REG_PC_NGUI_CTLSTAT, temp); - for (tries = 1000000; tries != 0; tries--) { + WHILE_NOT_TIMEOUT(.2) { if ((MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT) & R128_PC_BUSY) != R128_PC_BUSY) break; } } - if (tries == 0) + if (TIMEDOUT()) ErrorF("Timeout flushing pixel cache.\n"); } @@ -184,7 +186,6 @@ ATIEngineReset(ATIScreenInfo *atis) } else { MMIO_OUT32(mmio, RADEON_REG_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | @@ -235,28 +236,31 @@ ATIWaitAvailMMIO(ATIScreenInfo *atis, int n) { ATICardInfo *atic = atis->atic; char *mmio = atic->reg_base; - int tries; + TIMEOUT_LOCALS; if (atis->mmio_avail >= n) { atis->mmio_avail -= n; return; } if (atic->is_radeon) { - for (tries = 1000000; tries != 0 && atis->mmio_avail < n; tries--) - { + WHILE_NOT_TIMEOUT(.2) { atis->mmio_avail = MMIO_IN32(mmio, RADEON_REG_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; + if (atis->mmio_avail >= n) + break; } } else { - for (tries = 1000000; tries != 0 && atis->mmio_avail < n; tries--) - { + WHILE_NOT_TIMEOUT(.2) { atis->mmio_avail = MMIO_IN32(mmio, R128_REG_GUI_STAT) & 0xfff; + if (atis->mmio_avail >= n) + break; } } - if (tries == 0) { + if (TIMEDOUT()) { ErrorF("Timeout waiting for %d MMIO slots.\n", n); ATIEngineReset(atis); + ATIDrawSetup(atis->screen->pScreen); } atis->mmio_avail -= n; } @@ -291,23 +295,25 @@ ATIGetAvailPrimary(ATIScreenInfo *atis) static void ATIWaitAvailPrimary(ATIScreenInfo *atis, int n) { - int tries; + TIMEOUT_LOCALS; if (atis->cce_pri_avail >= n) { atis->cce_pri_avail -= n; return; } - for (tries = 1000000; tries != 0 && atis->cce_pri_avail < n; tries--) - { + WHILE_NOT_TIMEOUT(.2) { + if (atis->cce_pri_avail >= n) + break; atis->cce_pri_avail = ATIGetAvailPrimary(atis); if (atis->cce_pri_avail >= n) break; } - if (tries == 0) { + if (TIMEDOUT()) { ErrorF("Timeout waiting for %d CCE slots (%d avail).\n", n, atis->cce_pri_avail); ATIEngineReset(atis); + ATIDrawSetup(atis->screen->pScreen); } atis->cce_pri_avail -= n; } @@ -316,24 +322,24 @@ void ATIWaitIdle(ATIScreenInfo *atis) { ATICardInfo *atic = atis->atic; - int tries; char *mmio = atic->reg_base; RING_LOCALS; + TIMEOUT_LOCALS; if (atis->indirectBuffer != NULL) ATIFlushIndirect(atis, 0); #ifdef USE_DRI if (atis->using_dri) { - int ret; + int ret = 0; int cmd = (atic->is_radeon ? DRM_RADEON_CP_IDLE : DRM_R128_CCE_IDLE); - for (tries = 100; tries != 0; tries--) { + WHILE_NOT_TIMEOUT(2) { ret = drmCommandNone(atic->drmFd, cmd); if (ret != -EBUSY) break; } - if (tries == 0) { + if (TIMEDOUT()) { ATIDebugFifo(atis); FatalError("Timed out idling CCE (card hung)\n"); } @@ -356,14 +362,15 @@ ATIWaitIdle(ATIScreenInfo *atis) if (!atic->is_radeon && (atis->using_pseudo || atis->using_dma)) { ATIWaitAvailPrimary(atis, atis->cce_pri_size); - for (tries = 1000000; tries != 0; tries--) { + WHILE_NOT_TIMEOUT(.2) { if ((MMIO_IN32(mmio, R128_REG_PM4_STAT) & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE)) == 0) break; } - if (tries == 0) { + if (TIMEDOUT()) { ErrorF("Timeout idling CCE, resetting...\n"); ATIEngineReset(atis); + ATIDrawSetup(atis->screen->pScreen); } } @@ -373,21 +380,22 @@ ATIWaitIdle(ATIScreenInfo *atis) ATIWaitAvailMMIO(atis, 64); if (atic->is_radeon) { - for (tries = 1000000; tries != 0; tries--) { + WHILE_NOT_TIMEOUT(.2) { if ((MMIO_IN32(mmio, RADEON_REG_RBBM_STATUS) & RADEON_RBBM_ACTIVE) == 0) break; } } else { - for (tries = 1000000; tries != 0; tries--) { + WHILE_NOT_TIMEOUT(.2) { if ((MMIO_IN32(mmio, R128_REG_GUI_STAT) & R128_GUI_ACTIVE) == 0) break; } } - if (tries == 0) { + if (TIMEDOUT()) { ErrorF("Timeout idling accelerator, resetting...\n"); ATIEngineReset(atis); + ATIDrawSetup(atis->screen->pScreen); } } @@ -580,12 +588,16 @@ RadeonDispatchIndirectPDMA(ATIScreenInfo *atis) char *mmio = atic->reg_base; CARD32 *addr; int count, avail, reg, i; + TIMEOUT_LOCALS; addr = (CARD32 *)((char *)buf->address + atis->indirectStart); count = (buf->used - atis->indirectStart) / 4; reg = RADEON_REG_CSQ_APER_PRIMARY; - while (count > 0) { + WHILE_NOT_TIMEOUT(3) { + /* 3 seconds is empirical, using render_bench on an r100. */ + if (count <= 0) + break; avail = ATIGetAvailPrimary(atis); for (i = 0; i < min(count, avail); i++) { MMIO_OUT32(mmio, reg, *addr++); @@ -596,6 +608,11 @@ RadeonDispatchIndirectPDMA(ATIScreenInfo *atis) } count -= i; } + if (TIMEDOUT()) { + ErrorF("Timeout submitting packets, resetting...\n"); + ATIEngineReset(atis); + ATIDrawSetup(atis->screen->pScreen); + } } @@ -610,26 +627,30 @@ R128DispatchIndirectDMA(ATIScreenInfo *atis) char *mmio = atic->reg_base; CARD32 *addr; int count, ring_count; + TIMEOUT_LOCALS; addr = (CARD32 *)((char *)buf->address + atis->indirectStart); count = (buf->used - atis->indirectStart) / 4; ring_count = atis->ring_len / 4; - while (count > 0) { - int tries = 0; + WHILE_NOT_TIMEOUT(.2) { + if (count <= 0) + break; atis->ring_addr[atis->ring_write++] = *addr++; if (atis->ring_write >= ring_count) atis->ring_write = 0; while (atis->ring_write == atis->ring_read) { atis->ring_read = MMIO_IN32(mmio, ATI_REG_CCE_RPTR); - if (tries++ == 1000000) { - ErrorF("Timeout submitting packets, resetting...\n"); - ATIEngineReset(atis); - } } count--; } + if (TIMEDOUT()) { + ErrorF("Timeout submitting packets, resetting...\n"); + ATIEngineReset(atis); + ATIDrawSetup(atis->screen->pScreen); + } + /* Workaround for some early Rage 128 ASIC spins where the CCE parser * may read up to 32 DWORDS beyond the end of the ring buffer memory * before wrapping around, if the ring buffer was empty and a <32 DWORD diff --git a/hw/kdrive/ati/ati_dma.h b/hw/kdrive/ati/ati_dma.h index 76c7733de..62501fa8f 100644 --- a/hw/kdrive/ati/ati_dma.h +++ b/hw/kdrive/ati/ati_dma.h @@ -84,6 +84,27 @@ do { \ OUT_RING(val); \ } while (0) +#define TIMEOUT_LOCALS struct timeval _target, _curtime + +static inline Bool +tv_le(struct timeval *tv1, struct timeval *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec || + (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec < tv2->tv_usec)) + return TRUE; + else + return FALSE; +} + +#define WHILE_NOT_TIMEOUT(_timeout) \ + gettimeofday(&_target, NULL); \ + _target.tv_usec += ((_timeout) * 1000000); \ + _target.tv_sec += _target.tv_usec / 1000000; \ + _target.tv_usec = _target.tv_usec % 1000000; \ + while (gettimeofday(&_curtime, NULL), tv_le(&_curtime, &_target)) + +#define TIMEDOUT() (!tv_le(&_curtime, &_target)) + dmaBuf * ATIGetDMABuffer(ATIScreenInfo *atis); diff --git a/hw/kdrive/ati/ati_dri.c b/hw/kdrive/ati/ati_dri.c index 9b792b158..1ac75cf0a 100644 --- a/hw/kdrive/ati/ati_dri.c +++ b/hw/kdrive/ati/ati_dri.c @@ -23,6 +23,8 @@ */ /* $Header$ */ +#include <sys/time.h> + #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -1106,7 +1108,8 @@ ATIDRIGetBuffer(ATIScreenInfo *atis) drmBufPtr buf = NULL; int indx = 0; int size = 0; - int ret, tries; + int ret; + TIMEOUT_LOCALS; dma.context = atis->serverContext; dma.send_count = 0; @@ -1122,12 +1125,12 @@ ATIDRIGetBuffer(ATIScreenInfo *atis) dma.request_sizes = &size; dma.granted_count = 0; - for (tries = 100; tries != 0; tries--) { + WHILE_NOT_TIMEOUT(.2) { ret = drmDMA(atic->drmFd, &dma); if (ret != -EBUSY) break; } - if (tries == 0) + if (TIMEDOUT()) FatalError("Timeout fetching DMA buffer (card hung)\n"); if (ret != 0) FatalError("Error fetching DMA buffer: %d\n", ret); |