diff --git a/src/uxa/intel.h b/src/uxa/intel.h
index f05b160..922b208 100644
--- a/src/uxa/intel.h
+++ b/src/uxa/intel.h
@@ -395,6 +395,25 @@ extern void intel_mode_disable_unused_functions(ScrnInfoPtr scrn);
 extern void intel_mode_remove_fb(intel_screen_private *intel);
 extern void intel_mode_close(intel_screen_private *intel);
 extern void intel_mode_fini(intel_screen_private *intel);
+extern int intel_mode_read_drm_events(intel_screen_private *intel);
+
+typedef void (*intel_drm_handler_proc)(ScrnInfoPtr scrn,
+                                       xf86CrtcPtr crtc,
+                                       uint64_t seq,
+                                       uint64_t usec,
+                                       void *data);
+
+typedef void (*intel_drm_abort_proc)(ScrnInfoPtr scrn,
+                                     xf86CrtcPtr crtc,
+                                     void *data);
+
+extern uint32_t intel_drm_queue_alloc(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data, intel_drm_handler_proc handler, intel_drm_abort_proc abort);
+extern void intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), void *match_data);
+
+/* struct intel_mode *
+   intel_page_flip_handler(void *event_data); */
+
+
 
 extern int intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
 extern int intel_crtc_id(xf86CrtcPtr crtc);
@@ -422,6 +441,12 @@ typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
 				 CARD64 ust, CARD64 msc, CARD64 sbc);
 #endif
 
+typedef void (*intel_pageflip_handler_proc) (uint64_t frame,
+                                             uint64_t usec,
+                                             void *data);
+
+typedef void (*intel_pageflip_abort_proc) (void *data);
+
 typedef struct _DRI2FrameEvent {
 	struct intel_screen_private *intel;
 
@@ -444,7 +469,11 @@ typedef struct _DRI2FrameEvent {
 
 extern Bool intel_do_pageflip(intel_screen_private *intel,
 			      dri_bo *new_front,
-			      DRI2FrameEventPtr flip_info, int ref_crtc_hw_id);
+                              int ref_crtc_hw_id,
+                              Bool async,
+                              void *pageflip_data,
+                              intel_pageflip_handler_proc pageflip_handler,
+                              intel_pageflip_abort_proc pageflip_abort);
 
 static inline intel_screen_private *
 intel_get_screen_private(ScrnInfoPtr scrn)
diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
index 09cd48f..e6cc07a 100644
--- a/src/uxa/intel_display.c
+++ b/src/uxa/intel_display.c
@@ -61,6 +61,23 @@
 
 #define KNOWN_MODE_FLAGS ((1<<14)-1)
 
+struct intel_drm_queue {
+        struct xorg_list        list;
+        xf86CrtcPtr             crtc;
+        uint32_t                seq;
+        void                    *data;
+        ScrnInfoPtr             scrn;
+        intel_drm_handler_proc  handler;
+        intel_drm_abort_proc    abort;
+};
+
+static void
+intel_drm_abort_scrn(ScrnInfoPtr scrn);
+
+static uint32_t intel_drm_seq;
+
+static struct xorg_list intel_drm_queue;
+
 struct intel_mode {
 	int fd;
 	uint32_t fb_id;
@@ -68,7 +85,6 @@ struct intel_mode {
 	int cpp;
 
 	drmEventContext event_context;
-	DRI2FrameEventPtr flip_info;
 	int old_fb_id;
 	int flip_count;
 	uint64_t fe_msc;
@@ -76,6 +92,10 @@ struct intel_mode {
 
 	struct list outputs;
 	struct list crtcs;
+
+        void *pageflip_data;
+        intel_pageflip_handler_proc pageflip_handler;
+        intel_pageflip_abort_proc pageflip_abort;
 };
 
 struct intel_pageflip {
@@ -536,6 +556,7 @@ intel_crtc_apply(xf86CrtcPtr crtc)
 
 	if (scrn->pScreen)
 		xf86_reload_cursors(scrn->pScreen);
+        intel_drm_abort_scrn(scrn);
 
 done:
 	free(output_ids);
@@ -1138,11 +1159,23 @@ intel_output_dpms(xf86OutputPtr output, int dpms)
 							    dpms);
 			intel_output->dpms_mode = dpms;
 			drmModeFreeProperty(props);
-			return;
+                        break;
 		}
 
 		drmModeFreeProperty(props);
 	}
+
+        /* Make sure the associated CRTC is bound to the right fb_id; it won't be if
+         * a page flip happened while this CRTC was turned off
+         */
+        if (dpms == DPMSModeOn) {
+                xf86CrtcPtr             crtc = output->crtc;
+                struct intel_crtc       *intel_crtc = crtc->driver_private;
+                drmModeCrtcPtr          drm_crtc = drmModeGetCrtc(mode->fd, crtc_id(intel_crtc));
+
+                if (drm_crtc->buffer_id != mode->fb_id)
+                        intel_crtc_apply(crtc);
+        }
 }
 
 int
@@ -1614,10 +1647,27 @@ fail:
 	return FALSE;
 }
 
+static void
+intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
+                        uint64_t frame, uint64_t usec, void *data);
+
+static void
+intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data);
+
+static void
+intel_pageflip_complete(struct intel_mode *mode);
+
+static void
+intel_drm_abort_seq (ScrnInfoPtr scrn, uint32_t seq);
+
 Bool
 intel_do_pageflip(intel_screen_private *intel,
 		  dri_bo *new_front,
-		  DRI2FrameEventPtr flip_info, int ref_crtc_hw_id)
+                  int ref_crtc_hw_id,
+                  Bool async,
+                  void *pageflip_data,
+                  intel_pageflip_handler_proc pageflip_handler,
+                  intel_pageflip_abort_proc pageflip_abort)
 {
 	ScrnInfoPtr scrn = intel->scrn;
 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1626,6 +1676,8 @@ intel_do_pageflip(intel_screen_private *intel,
 	unsigned int pitch = scrn->displayWidth * intel->cpp;
 	struct intel_pageflip *flip;
 	uint32_t new_fb_id;
+        uint32_t flags;
+        uint32_t seq;
 	int i;
 
 	/*
@@ -1640,6 +1692,10 @@ intel_do_pageflip(intel_screen_private *intel,
 	intel_glamor_flush(intel);
 	intel_batch_submit(scrn);
 
+        mode->pageflip_data = pageflip_data;
+	mode->pageflip_handler = pageflip_handler;
+        mode->pageflip_abort = pageflip_abort;
+
 	/*
 	 * Queue flips on all enabled CRTCs
 	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
@@ -1652,13 +1708,13 @@ intel_do_pageflip(intel_screen_private *intel,
 	mode->fe_msc = 0;
 	mode->fe_usec = 0;
 
+        flags = DRM_MODE_PAGE_FLIP_EVENT;
+        if (async)
+                flags |= DRM_MODE_PAGE_FLIP_ASYNC;
 	for (i = 0; i < config->num_crtc; i++) {
 		if (!intel_crtc_on(config->crtc[i]))
 			continue;
 
-		mode->flip_info = flip_info;
-		mode->flip_count++;
-
 		crtc = config->crtc[i]->driver_private;
 
 		flip = calloc(1, sizeof(struct intel_pageflip));
@@ -1674,19 +1730,39 @@ intel_do_pageflip(intel_screen_private *intel,
 		flip->dispatch_me = (intel_crtc_to_pipe(crtc->crtc) == ref_crtc_hw_id);
 		flip->mode = mode;
 
+                seq = intel_drm_queue_alloc(scrn, config->crtc[i], flip, intel_pageflip_handler, intel_pageflip_abort);
+                if (!seq) {
+                        free(flip);
+                        goto error_undo;
+                }
+
+        again:
 		if (drmModePageFlip(mode->fd,
 				    crtc_id(crtc),
 				    new_fb_id,
-				    DRM_MODE_PAGE_FLIP_EVENT, flip)) {
+				    flags, (void *) seq))
+                {
+                        if (intel_mode_read_drm_events(intel)) {
+                                xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                                           "flip queue retry\n");
+                                goto again;
+                        }
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue failed: %s\n", strerror(errno));
+                        if (seq)
+                                intel_drm_abort_seq(scrn, seq);
 			free(flip);
 			goto error_undo;
 		}
+		mode->flip_count++;
 	}
 
 	mode->old_fb_id = mode->fb_id;
 	mode->fb_id = new_fb_id;
+
+        if (!mode->flip_count)
+                intel_pageflip_complete(mode);
+
 	return TRUE;
 
 error_undo:
@@ -1699,6 +1775,8 @@ error_undo:
 error_out:
 	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
 		   strerror(errno));
+
+        mode->flip_count = 0;
 	return FALSE;
 }
 
@@ -1706,6 +1784,98 @@ static const xf86CrtcConfigFuncsRec intel_xf86crtc_config_funcs = {
 	intel_xf86crtc_resize
 };
 
+/*
+ * Enqueue a potential drm response; when the associated response
+ * appears, we've got data to pass to the handler from here
+ */
+uint32_t
+intel_drm_queue_alloc(ScrnInfoPtr scrn,
+                      xf86CrtcPtr crtc,
+                      void *data,
+                      intel_drm_handler_proc handler,
+                      intel_drm_abort_proc abort)
+{
+        struct intel_drm_queue  *q;
+
+        q = calloc (1, sizeof (struct intel_drm_queue));
+
+        if (!q)
+                return 0;
+        if (!intel_drm_seq)
+                ++intel_drm_seq;
+        q->seq = intel_drm_seq++;
+        q->scrn = scrn;
+        q->crtc = crtc;
+        q->data = data;
+        q->handler = handler;
+        q->abort = abort;
+
+        xorg_list_add (&q->list, &intel_drm_queue);
+
+        return q->seq;
+}
+
+/*
+ * Abort one queued DRM entry, removing it
+ * from the list, calling the abort function and
+ * freeing the memory
+ */
+static void
+intel_drm_abort_one(struct intel_drm_queue *q)
+{
+        xorg_list_del(&q->list);
+        (*q->abort) (q->scrn, q->crtc, q->data);
+        free(q);
+}
+
+/*
+ * Externally usable abort function that uses a callback to match a single queued
+ * entry to abort
+ */
+void
+intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), void *match_data)
+{
+        struct intel_drm_queue  *q, *tmp;
+
+        xorg_list_for_each_entry_safe(q, tmp, &intel_drm_queue, list) {
+                if (match (q->data, match_data)) {
+                        intel_drm_abort_one(q);
+                        break;
+                }
+        }
+}
+
+/*
+ * Abort by drm queue sequence number
+ */
+static void
+intel_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq)
+{
+        struct intel_drm_queue  *q, *tmp;
+
+        xorg_list_for_each_entry_safe(q, tmp, &intel_drm_queue, list) {
+                if (q->seq == seq) {
+                        intel_drm_abort_one(q);
+                        break;
+                }
+        }
+}
+
+/*
+ * Abort all queued entries on a specific scrn, used
+ * when resetting the X server
+ */
+static void
+intel_drm_abort_scrn(ScrnInfoPtr scrn)
+{
+        struct intel_drm_queue  *q, *tmp;
+
+        xorg_list_for_each_entry_safe(q, tmp, &intel_drm_queue, list) {
+                if (q->scrn == scrn)
+                        intel_drm_abort_one(q);
+        }
+}
+
 static uint32_t pipe_select(int pipe)
 {
 	if (pipe > 1)
@@ -1802,44 +1972,111 @@ intel_crtc_msc_to_sequence(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t expect)
         return (uint32_t) (expect - intel_crtc->vblank_offset);
 }
 
+/*
+ * General DRM kernel handler. Looks for the matching sequence number in the
+ * drm event queue and calls the handler for it.
+ */
 static void
-intel_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
-		       unsigned int tv_usec, void *event)
+intel_drm_handler(int fd, uint32_t frame, uint32_t sec, uint32_t usec, void *user_ptr)
 {
-	I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event);
+        struct intel_drm_queue  *q, *tmp;
+        uint32_t                user_data = (uint32_t) (intptr_t) user_ptr;
+
+        xorg_list_for_each_entry_safe(q, tmp, &intel_drm_queue, list) {
+                if (q->seq == user_data) {
+                        uint64_t                msc;
+
+                        msc = intel_sequence_to_crtc_msc(q->crtc, frame);
+                        xorg_list_del(&q->list);
+                        (*q->handler) (q->scrn, q->crtc, msc, (uint64_t) sec * 1000000 + usec, q->data);
+                        free(q);
+                        break;
+                }
+        }
 }
 
+
+/*
+ * Notify the page flip caller that the flip is
+ * complete
+ */
 static void
-intel_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
-			  unsigned int tv_usec, void *event_data)
+intel_pageflip_complete(struct intel_mode *mode)
+{
+	/* Release framebuffer */
+	drmModeRmFB(mode->fd, mode->old_fb_id);
+
+        if (!mode->pageflip_handler)
+                return;
+
+        (*mode->pageflip_handler) (mode->fe_msc, mode->fe_usec,
+                                   mode->pageflip_data);
+}
+
+/*
+ * One pageflip event has completed. Update the saved msc/ust values
+ * as needed, then check to see if the whole set of events are
+ * complete and notify the application at that point
+ */
+static struct intel_mode *
+intel_handle_pageflip(struct intel_pageflip *flip, uint64_t msc, uint64_t usec)
 {
-	struct intel_pageflip *flip = event_data;
-	struct intel_mode *mode = flip->mode;
+	struct intel_mode       *mode = flip->mode;
 
-	/* Is this the event whose info shall be delivered to higher level? */
 	if (flip->dispatch_me) {
 		/* Yes: Cache msc, ust for later delivery. */
-		mode->fe_msc = frame;
-		mode->fe_usec = (uint64_t) tv_sec * 1000000 + tv_usec;
+		mode->fe_msc = msc;
+		mode->fe_usec = usec;
 	}
 	free(flip);
 
 	/* Last crtc completed flip? */
 	mode->flip_count--;
 	if (mode->flip_count > 0)
-		return;
+		return NULL;
+
+        return mode;
+}
+
+/*
+ * Called from the DRM event queue when a single flip has completed
+ */
+static void
+intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
+                        uint64_t msc, uint64_t usec, void *data)
+{
+	struct intel_pageflip   *flip = data;
+        struct intel_mode       *mode = intel_handle_pageflip(flip, msc, usec);
+
+        if (!mode)
+                return;
+        intel_pageflip_complete(mode);
+}
+
+/*
+ * Called from the DRM queue abort code when a flip has been aborted
+ */
+static void
+intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data)
+{
+	struct intel_pageflip   *flip = data;
+        struct intel_mode       *mode = intel_handle_pageflip(flip, 0, 0);
+
+        if (!mode)
+                return;
 
 	/* Release framebuffer */
 	drmModeRmFB(mode->fd, mode->old_fb_id);
 
-	if (mode->flip_info == NULL)
-		return;
+        if (!mode->pageflip_abort)
+                return;
 
-	/* Deliver cached msc, ust from reference crtc to flip event handler */
-	I830DRI2FlipEventHandler((uint32_t) mode->fe_msc, mode->fe_usec / 1000000,
-				 mode->fe_usec % 1000000, mode->flip_info);
+        (*mode->pageflip_abort) (mode->pageflip_data);
 }
 
+/*
+ * Check for pending DRM events and process them.
+ */
 static void
 drm_wakeup_handler(pointer data, int err, pointer p)
 {
@@ -1855,6 +2092,17 @@ drm_wakeup_handler(pointer data, int err, pointer p)
 		drmHandleEvent(mode->fd, &mode->event_context);
 }
 
+/*
+ * Just try to read drm_events; the fd is non-blocking, so we'll get
+ * zero if there aren't any events to read
+ */
+int
+intel_mode_read_drm_events(struct intel_screen_private *intel)
+{
+        struct intel_mode *mode = intel->modes;
+        return drmHandleEvent(mode->fd, &mode->event_context);
+}
+
 static drmModeEncoderPtr
 intel_get_kencoder(struct intel_mode *mode, int num)
 {
@@ -1954,8 +2202,12 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
 	xf86InitialConfiguration(scrn, TRUE);
 
 	mode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
-	mode->event_context.vblank_handler = intel_vblank_handler;
-	mode->event_context.page_flip_handler = intel_page_flip_handler;
+        mode->event_context.vblank_handler = intel_drm_handler;
+        mode->event_context.page_flip_handler = intel_drm_handler;
+
+        /* XXX assumes only one intel screen */
+        xorg_list_init(&intel_drm_queue);
+        intel_drm_seq = 0;
 
 	has_flipping = 0;
 	gp.param = I915_PARAM_HAS_PAGEFLIPPING;
@@ -1998,14 +2250,6 @@ intel_mode_remove_fb(intel_screen_private *intel)
 	}
 }
 
-static Bool has_pending_events(int fd)
-{
-	struct pollfd pfd;
-	pfd.fd = fd;
-	pfd.events = POLLIN;
-	return poll(&pfd, 1, 0) == 1;
-}
-
 void
 intel_mode_close(intel_screen_private *intel)
 {
@@ -2014,8 +2258,7 @@ intel_mode_close(intel_screen_private *intel)
 	if (mode == NULL)
 		return;
 
-	while (has_pending_events(mode->fd))
-		drmHandleEvent(mode->fd, &mode->event_context);
+        intel_drm_abort_scrn(intel->scrn);
 
 	RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
 				     drm_wakeup_handler, mode);
@@ -2094,7 +2337,8 @@ Bool intel_crtc_on(xf86CrtcPtr crtc)
 		return FALSE;
 
 	ret = (drm_crtc->mode_valid &&
-	       intel_crtc->mode->fb_id == drm_crtc->buffer_id);
+	       (intel_crtc->mode->fb_id == drm_crtc->buffer_id ||
+                intel_crtc->mode->old_fb_id == drm_crtc->buffer_id));
 	free(drm_crtc);
 
 	return ret;
diff --git a/src/uxa/intel_dri.c b/src/uxa/intel_dri.c
index 9c2aafd..df07917 100644
--- a/src/uxa/intel_dri.c
+++ b/src/uxa/intel_dri.c
@@ -592,7 +592,7 @@ I830DRI2DrawableCrtc(DrawablePtr pDraw)
 
 	/* Make sure the CRTC is valid and this is the real front buffer */
 	if (crtc != NULL && !crtc->rotatedData)
-		return crtc;
+                return crtc;
 
 	return NULL;
 }
@@ -725,15 +725,15 @@ i830_dri2_add_frame_event(DRI2FrameEventPtr info)
 }
 
 static void
-i830_dri2_del_frame_event(DrawablePtr drawable, DRI2FrameEventPtr info)
+i830_dri2_del_frame_event(DRI2FrameEventPtr info)
 {
 	list_del(&info->client_resource);
 	list_del(&info->drawable_resource);
 
 	if (info->front)
-		I830DRI2DestroyBuffer(drawable, info->front);
+		I830DRI2DestroyBuffer(NULL, info->front);
 	if (info->back)
-		I830DRI2DestroyBuffer(drawable, info->back);
+		I830DRI2DestroyBuffer(NULL, info->back);
 
 	free(info);
 }
@@ -831,6 +831,24 @@ static drm_intel_bo *get_pixmap_bo(I830DRI2BufferPrivatePtr priv)
 	return bo;
 }
 
+static void
+I830DRI2FlipComplete(uint64_t frame, uint64_t usec, void *pageflip_data)
+{
+        DRI2FrameEventPtr info = pageflip_data;
+
+        I830DRI2FlipEventHandler((uint32_t) frame, usec / 1000000,
+                                 usec % 1000000,
+                                 info);
+}
+
+static void
+I830DRI2FlipAbort(void *pageflip_data)
+{
+        DRI2FrameEventPtr info = pageflip_data;
+
+        i830_dri2_del_frame_event(info);
+}
+
 /*
  * Our internal swap routine takes care of actually exchanging, blitting, or
  * flipping buffers as necessary.
@@ -848,7 +866,9 @@ I830DRI2ScheduleFlip(struct intel_screen_private *intel,
 		info->type = DRI2_SWAP;
 		if (!intel_do_pageflip(intel,
 				       get_pixmap_bo(priv),
-				       info, info->pipe))
+				       info->pipe, FALSE, info,
+                                       I830DRI2FlipComplete,
+                                       I830DRI2FlipAbort))
 			return FALSE;
 
 		I830DRI2ExchangeBuffers(intel, info->front, info->back);
@@ -903,7 +923,7 @@ I830DRI2ScheduleFlip(struct intel_screen_private *intel,
 	}
 
 	old_back = get_pixmap_bo(priv);
-	if (!intel_do_pageflip(intel, old_back, info, info->pipe)) {
+	if (!intel_do_pageflip(intel, old_back, info->pipe, FALSE, info, I830DRI2FlipComplete, I830DRI2FlipAbort)) {
 		intel->back_buffer = new_back;
 		return FALSE;
 	}
@@ -999,7 +1019,7 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 		status = dixLookupDrawable(&drawable, swap_info->drawable_id, serverClient,
 					   M_ANY, DixWriteAccess);
 	if (status != Success) {
-		i830_dri2_del_frame_event(NULL, swap_info);
+		i830_dri2_del_frame_event(swap_info);
 		return;
 	}
 
@@ -1033,7 +1053,7 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 		break;
 	}
 
-	i830_dri2_del_frame_event(drawable, swap_info);
+	i830_dri2_del_frame_event(swap_info);
 }
 
 void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
@@ -1094,7 +1114,7 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
 						   serverClient,
 						   M_ANY, DixWriteAccess);
 			if (chain_drawable == NULL) {
-				i830_dri2_del_frame_event(chain_drawable, chain);
+				i830_dri2_del_frame_event(chain);
 			} else if (!can_exchange(chain_drawable, chain->front, chain->back) ||
 				   !I830DRI2ScheduleFlip(intel, chain_drawable, chain)) {
 				I830DRI2FallbackBlitSwap(chain_drawable,
@@ -1105,7 +1125,7 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
 						 DRI2_BLIT_COMPLETE,
 						 chain->client ? chain->event_complete : NULL,
 						 chain->event_data);
-				i830_dri2_del_frame_event(chain_drawable, chain);
+				i830_dri2_del_frame_event(chain);
 			}
 		}
 		break;
@@ -1117,7 +1137,7 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
 		break;
 	}
 
-	i830_dri2_del_frame_event(drawable, flip_info);
+	i830_dri2_del_frame_event(flip_info);
 }
 
 static uint32_t pipe_select(int pipe)
@@ -1130,6 +1150,28 @@ static uint32_t pipe_select(int pipe)
 		return 0;
 }
 
+static void
+intel_dri2_vblank_handler(ScrnInfoPtr scrn,
+                          xf86CrtcPtr crtc,
+                          uint64_t msc,
+                          uint64_t usec,
+                          void *data)
+{
+        DRI2FrameEventPtr swap_info = data;
+
+        I830DRI2FrameEventHandler((uint32_t) msc, usec / 1000000, usec % 1000000, swap_info);
+}
+
+static void
+intel_dri2_vblank_abort(ScrnInfoPtr scrn,
+                        xf86CrtcPtr crtc,
+                        void *data)
+{
+        DRI2FrameEventPtr swap_info = data;
+
+        i830_dri2_del_frame_event(swap_info);
+}
+
 /*
  * ScheduleSwap is responsible for requesting a DRM vblank event for the
  * appropriate frame.
@@ -1167,6 +1209,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	enum DRI2FrameEventType swap_type = DRI2_SWAP;
 	uint64_t current_msc, current_ust;
         uint64_t request_msc;
+        uint32_t seq;
 
 	/* Drawable not displayed... just complete the swap */
 	if (pipe == -1)
@@ -1243,8 +1286,13 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		if (current_msc >= *target_msc)
 			*target_msc = current_msc;
 
+                seq = intel_drm_queue_alloc(scrn, crtc, swap_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
+                if (!seq)
+                        goto blit_fallback;
+
 		vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, *target_msc);
-		vbl.request.signal = (unsigned long)swap_info;
+		vbl.request.signal = (unsigned long)seq;
+
 		ret = drmWaitVBlank(intel->drmSubFD, &vbl);
 		if (ret) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1286,12 +1334,15 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	if (request_msc <= current_msc)
 		request_msc += divisor;
 
-        vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, request_msc);
+
+        seq = intel_drm_queue_alloc(scrn, crtc, swap_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
+        if (!seq)
+                goto blit_fallback;
 
 	/* Account for 1 frame extra pageflip delay if flip > 0 */
-	vbl.request.sequence -= flip;
+        vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, request_msc) - flip;
+	vbl.request.signal = (unsigned long)seq;
 
-	vbl.request.signal = (unsigned long)swap_info;
 	ret = drmWaitVBlank(intel->drmSubFD, &vbl);
 	if (ret) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1310,7 +1361,7 @@ blit_fallback:
 	I830DRI2FallbackBlitSwap(draw, front, back);
 	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
 	if (swap_info)
-	    i830_dri2_del_frame_event(draw, swap_info);
+	    i830_dri2_del_frame_event(swap_info);
 	*target_msc = 0; /* offscreen, so zero out target vblank count */
 	return TRUE;
 }
@@ -1371,6 +1422,7 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
         xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw);
         int pipe = crtc ? intel_crtc_to_pipe(crtc) : -1;
 	CARD64 current_msc, current_ust, request_msc;
+        uint32_t seq;
 
 	/* Drawable not visible, return immediately */
 	if (pipe == -1)
@@ -1406,12 +1458,17 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
 		 * sending us MSC targets from the past by forcibly updating
 		 * their count on this call.
 		 */
+                seq = intel_drm_queue_alloc(scrn, crtc, wait_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
+                if (!seq)
+                        goto out_free;
+
 		if (current_msc >= target_msc)
 			target_msc = current_msc;
 		vbl.request.type =
 			DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
 		vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, target_msc);
-		vbl.request.signal = (unsigned long)wait_info;
+		vbl.request.signal = (unsigned long)seq;
+
 		ret = drmWaitVBlank(intel->drmSubFD, &vbl);
 		if (ret) {
 			static int limit = 5;
@@ -1448,9 +1505,13 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
 	if ((current_msc % divisor) >= remainder)
                 request_msc += divisor;
 
+        seq = intel_drm_queue_alloc(scrn, crtc, wait_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
+        if (!seq)
+                goto out_free;
+
 	vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, request_msc);
+	vbl.request.signal = (unsigned long)seq;
 
-	vbl.request.signal = (unsigned long)wait_info;
 	ret = drmWaitVBlank(intel->drmSubFD, &vbl);
 	if (ret) {
 		static int limit = 5;
@@ -1470,7 +1531,7 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
 	return TRUE;
 
 out_free:
-	i830_dri2_del_frame_event(draw, wait_info);
+	i830_dri2_del_frame_event(wait_info);
 out_complete:
 	DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
 	return TRUE;
