if (ret)
                goto destroy_ringbuffer;
 
+       /* IIR "flip pending" bit means done if this bit is set */
+       if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
+               dev_priv->flip_pending_is_done = true;
+
        intel_modeset_init(dev);
 
        ret = drm_irq_install(dev);
 
        struct drm_crtc *plane_to_crtc_mapping[2];
        struct drm_crtc *pipe_to_crtc_mapping[2];
        wait_queue_head_t pending_flip_queue;
+       bool flip_pending_is_done;
 
        /* Reclocking support */
        bool render_reclock_avail;
 
                if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
                        DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
 
-               if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
+               if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
                        intel_prepare_page_flip(dev, 0);
+                       if (dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip_plane(dev, 0);
+               }
 
-               if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
+               if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
+                       if (dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip_plane(dev, 1);
                        intel_prepare_page_flip(dev, 1);
+               }
 
                if (pipea_stats & vblank_status) {
                        vblank++;
                        drm_handle_vblank(dev, 0);
-                       intel_finish_page_flip(dev, 0);
+                       if (!dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip(dev, 0);
                }
 
                if (pipeb_stats & vblank_status) {
                        vblank++;
                        drm_handle_vblank(dev, 1);
-                       intel_finish_page_flip(dev, 1);
+                       if (!dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip(dev, 1);
                }
 
                if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
 
 #define   MI_OVERLAY_OFF       (0x2<<21)
 #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
 #define MI_DISPLAY_FLIP                MI_INSTR(0x14, 2)
+#define MI_DISPLAY_FLIP_I915   MI_INSTR(0x14, 1)
 #define   MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
 #define MI_STORE_DWORD_IMM     MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL       (1 << 22) /* 965+ only */
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
 #define BB_ADDR                0x02140 /* 8 bytes */
 #define GFX_FLSH_CNTL  0x02170 /* 915+ only */
+#define ECOSKPD                0x021d0
+#define   ECO_GATING_CX_ONLY   (1<<3)
+#define   ECO_FLIP_DONE                (1<<0)
 
 /* GEN6 interrupt control */
 #define GEN6_RENDER_HWSTAM     0x2098
 
        kfree(work);
 }
 
-void intel_finish_page_flip(struct drm_device *dev, int pipe)
+static void do_intel_finish_page_flip(struct drm_device *dev,
+                                     struct drm_crtc *crtc)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
        struct drm_i915_gem_object *obj_priv;
        schedule_work(&work->work);
 }
 
+void intel_finish_page_flip(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+
+       do_intel_finish_page_flip(dev, crtc);
+}
+
+void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
+
+       do_intel_finish_page_flip(dev, crtc);
+}
+
 void intel_prepare_page_flip(struct drm_device *dev, int plane)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
                        ;
 
        BEGIN_LP_RING(4);
-       OUT_RING(MI_DISPLAY_FLIP |
-                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       OUT_RING(fb->pitch);
        if (IS_I965G(dev)) {
+               OUT_RING(MI_DISPLAY_FLIP |
+                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+               OUT_RING(fb->pitch);
                OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
                pipesrc = I915_READ(pipesrc_reg); 
                OUT_RING(pipesrc & 0x0fff0fff);
        } else {
+               OUT_RING(MI_DISPLAY_FLIP_I915 |
+                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+               OUT_RING(fb->pitch);
                OUT_RING(obj_priv->gtt_offset);
                OUT_RING(MI_NOOP);
        }
 
 
 extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
 extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
+extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
 
 extern void intel_setup_overlay(struct drm_device *dev);
 extern void intel_cleanup_overlay(struct drm_device *dev);