summaryrefslogtreecommitdiff
path: root/hw/kdrive/ati
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2005-01-20 16:22:04 +0000
committerEric Anholt <anholt@freebsd.org>2005-01-20 16:22:04 +0000
commit13c6b2f0b6c464ce11f6c332b2fa1a529bdbab01 (patch)
tree7be05625e56e69800350b1a47fa3734bb2e73736 /hw/kdrive/ati
parentdbe45c71590ac319250d04a2bf37ec07cd79e42a (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.c83
-rw-r--r--hw/kdrive/ati/ati_dma.h21
-rw-r--r--hw/kdrive/ati/ati_dri.c9
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);