summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Ziv <alonz@nolaviz.org>2007-07-30 22:47:59 +0300
committerMichel Dänzer <michel@tungstengraphics.com>2007-08-23 12:12:01 +0200
commitde26e406f52b3b13f03eee2b8023924ec6406f0a (patch)
tree8e842e5ded3b28eecb846bd91de5e68a5635ff47
parentc66e5de26ae93caa368213f3cce139aacec955d2 (diff)
radeon: Sane handling of timeouts in WaitForVerticalSync(2).
RADEONWaitForVerticalSync() and RADEONWaitForVerticalSync2() need to wait for a timeout specified in milliseconds; looping around usleep() causes the timeout to be unnecessarily long, as the OS may sleep longer than requested (on Linux the minimum actual sleep value may be several ms). The new logic uses gettimeofday() in the loop to see when the (absolute) timeout has arrived. Signed-off-by: Alon Ziv <alonz@nolaviz.org>
-rw-r--r--src/radeon.h21
-rw-r--r--src/radeon_driver.c20
2 files changed, 31 insertions, 10 deletions
diff --git a/src/radeon.h b/src/radeon.h
index bf1444c9..8babf391 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -39,6 +39,8 @@
#include <stdlib.h> /* For abs() */
#include <unistd.h> /* For usleep() */
+#include <sys/time.h> /* For
+#include <time.h> * gettimeofday() */
#include "xf86str.h"
#include "compiler.h"
@@ -159,6 +161,8 @@ typedef enum {
#define RADEON_IDLE_RETRY 16 /* Fall out of idle loops after this count */
#define RADEON_TIMEOUT 2000000 /* Fall out of wait loops after this count */
+#define RADEON_VSYNC_TIMEOUT 20000 /* Maximum wait for VSYNC (in usecs) */
+
/* Buffer are aligned on 4096 byte boundaries */
#define RADEON_BUFFER_ALIGN 0x00000fff
#define RADEON_VBIOS_SIZE 0x00010000
@@ -1224,4 +1228,21 @@ static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn)
#endif
}
+static __inline__ void radeon_init_timeout(struct timeval *endtime,
+ unsigned int timeout)
+{
+ gettimeofday(endtime, NULL);
+ endtime->tv_usec += timeout;
+ endtime->tv_sec += endtime->tv_usec / 1000000;
+ endtime->tv_usec %= 1000000;
+}
+
+static __inline__ int radeon_timedout(const struct timeval *endtime)
+{
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return now.tv_sec == endtime->tv_sec ?
+ now.tv_usec > endtime->tv_usec : now.tv_sec > endtime->tv_sec;
+}
+
#endif /* _RADEON_H_ */
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 87f14056..469e7bc3 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -724,7 +724,7 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn)
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
CARD32 crtc_gen_cntl;
- int i;
+ struct timeval timeout;
crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL);
if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) ||
@@ -735,10 +735,10 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn)
OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR);
/* Wait for it to go back up */
- for (i = 0; i < RADEON_TIMEOUT/1000; i++) {
- if (INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) break;
- usleep(1);
- }
+ radeon_init_timeout(&timeout, RADEON_VSYNC_TIMEOUT);
+ while (!(INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) &&
+ !radeon_timedout(&timeout))
+ usleep(100);
}
/* Wait for vertical sync on secondary CRTC */
@@ -747,7 +747,7 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn)
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
CARD32 crtc2_gen_cntl;
- int i;
+ struct timeval timeout;
crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) ||
@@ -758,10 +758,10 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn)
OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR);
/* Wait for it to go back up */
- for (i = 0; i < RADEON_TIMEOUT/1000; i++) {
- if (INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) break;
- usleep(1);
- }
+ radeon_init_timeout(&timeout, RADEON_VSYNC_TIMEOUT);
+ while (!(INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) &&
+ !radeon_timedout(&timeout))
+ usleep(100);
}