Index: radeon_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v
retrieving revision 1.20
diff -u -r1.20 radeon_context.c
--- radeon_context.c	2 Oct 2002 12:32:45 -0000	1.20
+++ radeon_context.c	8 Oct 2002 12:04:14 -0000
@@ -405,6 +405,7 @@
    radeonInitSwtcl( ctx );
 
    rmesa->do_irqs = (rmesa->radeonScreen->irq && !getenv("RADEON_NO_IRQS"));
+   rmesa->irqEmitted = GL_FALSE;
    rmesa->iw.irq_seq = -1;
 
    rmesa->do_usleeps = !getenv("RADEON_NO_USLEEPS");
Index: radeon_context.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.h,v
retrieving revision 1.16
diff -u -r1.16 radeon_context.h
--- radeon_context.h	2 Oct 2002 12:32:45 -0000	1.16
+++ radeon_context.h	8 Oct 2002 12:04:14 -0000
@@ -723,6 +723,7 @@
     */
    GLuint do_usleeps;
    GLuint do_irqs;
+   GLboolean irqEmitted;
    drmRadeonIrqWait iw;
 
    /* Drawable, cliprect and scissor information
Index: radeon_ioctl.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v
retrieving revision 1.30
diff -u -r1.30 radeon_ioctl.c
--- radeon_ioctl.c	4 Oct 2002 14:35:26 -0000	1.30
+++ radeon_ioctl.c	8 Oct 2002 12:04:15 -0000
@@ -615,89 +615,96 @@
  * SwapBuffers with client-side throttling
  */
 
-#define RADEON_MAX_OUTSTANDING	2
+#define RADEON_IRQ_THRESHOLD 2
 
 static void delay( void ) {
 /* Prevent an optimizing compiler from removing a spin loop */
 }
 
+static CARD32 radeonGetLastFrame (radeonContextPtr rmesa) {
+   unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
+   int ret;
+   CARD32 frame;
+
+   if (rmesa->dri.screen->drmMinor >= 4) {
+      drmRadeonGetParam gp;
+
+      gp.param = RADEON_PARAM_LAST_FRAME;
+      gp.value = (int *)&frame;
+      ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
+				 &gp, sizeof(gp) );
+   } else
+      ret = -EINVAL;
+
+   if ( ret == -EINVAL ) {
+      frame = INREG( RADEON_LAST_FRAME_REG );
+   } else if ( ret ) {
+      fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
+      exit(1);
+   }
+   if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+      fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)frame );
+      if ( ret ) fprintf( stderr, " ( RADEON_LAST_FRAME register read directly )\n" );
+   }
+
+   return frame;
+}
+
 static int radeonWaitForFrameCompletion( radeonContextPtr rmesa )
 {
    RADEONSAREAPrivPtr sarea = rmesa->sarea;
    int fd = rmesa->dri.fd;
    int wait = 0;
+   int ret;
 
-   if (rmesa->do_irqs) {
-      int ret;
-      drmRadeonIrqWait *iw = &rmesa->iw;
-      drmRadeonIrqEmit ie;
-
-      /* if there was a previous frame, wait for its IRQ */
-      if (iw->irq_seq != -1) {
-         UNLOCK_HARDWARE( rmesa ); 
-         do {
-	    ret = drmCommandWrite( fd, DRM_RADEON_IRQ_WAIT, iw, sizeof(*iw) );
-	 } while (ret && errno == EINTR);
-         if ( ret ) {
-            fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
-            exit(1);
-         }
-         LOCK_HARDWARE( rmesa ); 
-      }
-
-      /* emit an IRQ for this frame, will be waited for after the next frame */
-      ie.irq_seq = &iw->irq_seq;
-      ret = drmCommandWriteRead( fd, DRM_RADEON_IRQ_EMIT, &ie, sizeof(ie) );
-      if ( ret ) {
-         fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
-         exit(1);
+   if (rmesa->irqEmitted) {
+      if (radeonGetLastFrame (rmesa) < sarea->last_frame) {
+	 /* have to wait, justifies emission of another IRQ */
+	 wait = RADEON_IRQ_THRESHOLD;
+
+	 UNLOCK_HARDWARE( rmesa ); 
+	 do {
+	    ret = drmCommandWrite( fd, DRM_RADEON_IRQ_WAIT,
+				   &rmesa->iw, sizeof(rmesa->iw) );
+	 } while (ret && (errno == EINTR || errno == EAGAIN));
+	 if ( ret ) {
+	    fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
+	    exit(1);
+	 }
+	 LOCK_HARDWARE( rmesa ); 
       }
    } else {
-      unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
-      CARD32 frame;
-
-      while ( 1 ) {
-         int ret;
-
-         if (rmesa->dri.screen->drmMinor >= 4) {
-            drmRadeonGetParam gp;
-
-            gp.param = RADEON_PARAM_LAST_FRAME;
-            gp.value = (int *)&frame;
-            ret = drmCommandWriteRead( fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
-         } else
-            ret = -EINVAL;
-
-         if ( ret == -EINVAL ) {
-            frame = INREG( RADEON_LAST_FRAME_REG );
-         } else if ( ret ) {
-            fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
-            exit(1);
-         }
-         if ( RADEON_DEBUG & DEBUG_IOCTL ) {
-            fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)frame );
-            if ( ret ) fprintf( stderr, " ( RADEON_LAST_FRAME register read directly )\n" );
-         }
-
-         if ( sarea->last_frame - frame <= RADEON_MAX_OUTSTANDING ) {
-            break;
-         }
-         wait++;
-
-	 if (rmesa->do_usleeps) {
-	    UNLOCK_HARDWARE( rmesa );
-	    do_usleep(1, __FUNCTION__);
-	    LOCK_HARDWARE( rmesa );
+      /* no IRQ, busy waiting */
+      while (radeonGetLastFrame (rmesa) < sarea->last_frame) {
+	 wait++;
+	 if (rmesa->do_usleeps && !rmesa->do_irqs) {
+	    UNLOCK_HARDWARE( rmesa ); 
+	    do_usleep(1, __FUNCTION__); 
+	    LOCK_HARDWARE( rmesa ); 
 	 } else {
 	    int i;
 	    /* Spin in place a bit so we aren't hammering the bus */
-	    for ( i = 0 ; i < 1024 ; i++ ) {
+	    for ( i = 0 ; i < 10000 ; i++ ) {
 	       delay();
 	    }
 	 }
       }
    }
 
+   if (wait >= RADEON_IRQ_THRESHOLD && rmesa->do_irqs) {
+      drmRadeonIrqEmit ie;
+
+      ie.irq_seq = &rmesa->iw.irq_seq;
+      ret = drmCommandWriteRead( fd, DRM_RADEON_IRQ_EMIT, &ie, sizeof(ie) );
+      if ( ret ) {
+	 fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
+	 exit(1);
+      }
+      rmesa->irqEmitted = GL_TRUE;
+   } else {
+      rmesa->irqEmitted = GL_FALSE;
+   }
+
    if ( RADEON_DEBUG & DEBUG_IOCTL )
       fprintf(stderr, "%s( done, wait=%d )\n", __FUNCTION__, wait);
 
@@ -1152,7 +1159,7 @@
 
       do {
 	 ret = drmCommandWrite( fd, DRM_RADEON_IRQ_WAIT, &iw, sizeof(iw) );
-      } while (ret && errno == EINTR);
+      } while (ret && (errno == EINTR || errno == EAGAIN));
       if ( ret ) {
 	 fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
 	 exit(1);
