xserver/hw/kdrive/ati ati_dma.c, 1.6, 1.7 ati_dma.h, 1.3, 1.4 ati_dri.c, 1.13, 1.14

Eric Anholt xserver-commit@pdx.freedesktop.org
Thu Jan 20 08:22:06 PST 2005


Committed by: anholt

Update of /cvs/xserver/xserver/hw/kdrive/ati
In directory gabe:/tmp/cvs-serv16975/hw/kdrive/ati

Modified Files:
	ati_dma.c ati_dma.h ati_dri.c 
Log Message:
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.


Index: ati_dma.c
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/ati/ati_dma.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- ati_dma.c	20 Jan 2005 01:09:48 -0000	1.6
+++ ati_dma.c	20 Jan 2005 16:22:04 -0000	1.7
@@ -21,6 +21,8 @@
  */
 /* $Header$ */
 
+#include <sys/time.h>
+
 #include "ati.h"
 #include "ati_reg.h"
 #include "ati_dma.h"
@@ -115,15 +117,15 @@
 {
 	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 @@
 		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 @@
 		} 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 @@
 {
 	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 @@
 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 @@
 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 @@
 	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 @@
 		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 @@
 	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 @@
 		}
 		count -= i;
 	}
+	if (TIMEDOUT()) {
+		ErrorF("Timeout submitting packets, resetting...\n");
+		ATIEngineReset(atis);
+		ATIDrawSetup(atis->screen->pScreen);
+	}
 }
 
 
@@ -610,26 +627,30 @@
 	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

Index: ati_dma.h
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/ati/ati_dma.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- ati_dma.h	12 Sep 2004 19:52:51 -0000	1.3
+++ ati_dma.h	20 Jan 2005 16:22:04 -0000	1.4
@@ -84,6 +84,27 @@
 	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);
 

Index: ati_dri.c
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/ati/ati_dri.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- ati_dri.c	21 Dec 2004 09:49:30 -0000	1.13
+++ ati_dri.c	20 Jan 2005 16:22:04 -0000	1.14
@@ -23,6 +23,8 @@
  */
 /* $Header$ */
 
+#include <sys/time.h>
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -1106,7 +1108,8 @@
 	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 @@
 	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);



More information about the xserver-commit mailing list