Index: r200_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_context.c,v
retrieving revision 1.13
diff -u -r1.13 r200_context.c
--- r200_context.c	25 Oct 2002 20:28:44 -0000	1.13
+++ r200_context.c	28 Oct 2002 13:57:09 -0000
@@ -424,6 +424,7 @@
       rmesa->vblwait = GL_TRUE;
 
    rmesa->iw.irq_seq = -1;
+   rmesa->irqsEmitted = 0;
    rmesa->do_irqs = (rmesa->dri.drmMinor >= 6 && 
 		     !getenv("R200_NO_IRQS") &&
 		     rmesa->r200Screen->irq);
Index: r200_context.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_context.h,v
retrieving revision 1.7
diff -u -r1.7 r200_context.h
--- r200_context.h	10 Oct 2002 08:19:58 -0000	1.7
+++ r200_context.h	28 Oct 2002 13:57:10 -0000
@@ -803,6 +803,7 @@
     */
    GLuint do_usleeps;
    GLuint do_irqs;
+   GLuint irqsEmitted;
    drmRadeonIrqWait iw;
 
    /* Clientdata textures;
Index: r200_ioctl.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c,v
retrieving revision 1.10
diff -u -r1.10 r200_ioctl.c
--- r200_ioctl.c	9 Oct 2002 19:33:06 -0000	1.10
+++ r200_ioctl.c	28 Oct 2002 13:57:11 -0000
@@ -301,6 +301,12 @@
  * SwapBuffers with client-side throttling
  */
 
+#define R200_IRQ_THRESHOLD 2
+
+static void delay( void ) {
+/* Prevent an optimizing compiler from removing a spin loop */
+}
+
 static CARD32 r200GetLastFrame (r200ContextPtr rmesa) {
    drmRadeonGetParam gp;
    int ret;
@@ -322,38 +328,57 @@
 {
    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 && r200GetLastFrame( rmesa ) < sarea->last_frame ) {
-         UNLOCK_HARDWARE( rmesa ); 
-         do {
-	    ret = drmCommandWrite( fd, DRM_RADEON_IRQ_WAIT, iw, sizeof(*iw) );
+   if (rmesa->irqsEmitted) {
+      if (r200GetLastFrame (rmesa) < sarea->last_frame) {
+	 /* have to wait, justifies emission of another IRQ */
+	 wait = R200_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 ); 
+	 if ( ret ) {
+	    fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
+	    exit(1);
+	 }
+	 LOCK_HARDWARE( rmesa ); 
       }
+   } else {
+      /* no IRQ, busy waiting */
+      while (r200GetLastFrame (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 < 10000 ; i++ ) {
+	       delay();
+	    }
+	 }
+      }
+   }
 
-      /* emit an IRQ for this frame, will be waited for after the next frame */
-      ie.irq_seq = &iw->irq_seq;
+   /* give interrupts a second chance to avoid busy/irq "ping-ponging" */
+   if ((wait >= R200_IRQ_THRESHOLD || rmesa->irqsEmitted == 1) &&
+       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);
+	 fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
+	 exit(1);
       }
+      rmesa->irqsEmitted++;
    } else {
-      while ( sarea->last_frame < r200GetLastFrame( rmesa ) ) {
-         UNLOCK_HARDWARE( rmesa ); 
-         do_usleep(1, __FUNCTION__); 
-         LOCK_HARDWARE( rmesa ); 
-      }
+      rmesa->irqsEmitted = 0;
    }
 }
 
