#define vaddr(page) ((unsigned long)pfn_to_kaddr(page_to_pfn(page)))
 
-static int do_block_io_op(struct xen_blkif_ring *ring);
+static int do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags);
 static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
                                struct blkif_request *req,
                                struct pending_req *pending_req);
        struct xen_vbd *vbd = &blkif->vbd;
        unsigned long timeout;
        int ret;
+       bool do_eoi;
+       unsigned int eoi_flags = XEN_EOI_FLAG_SPURIOUS;
 
        set_freezable();
        while (!kthread_should_stop()) {
                if (timeout == 0)
                        goto purge_gnt_list;
 
+               do_eoi = ring->waiting_reqs;
+
                ring->waiting_reqs = 0;
                smp_mb(); /* clear flag *before* checking for work */
 
-               ret = do_block_io_op(ring);
+               ret = do_block_io_op(ring, &eoi_flags);
                if (ret > 0)
                        ring->waiting_reqs = 1;
                if (ret == -EACCES)
                        wait_event_interruptible(ring->shutdown_wq,
                                                 kthread_should_stop());
 
+               if (do_eoi && !ring->waiting_reqs) {
+                       xen_irq_lateeoi(ring->irq, eoi_flags);
+                       eoi_flags |= XEN_EOI_FLAG_SPURIOUS;
+               }
+
 purge_gnt_list:
                if (blkif->vbd.feature_gnt_persistent &&
                    time_after(jiffies, ring->next_lru)) {
  * and transmute  it to the block API to hand it over to the proper block disk.
  */
 static int
-__do_block_io_op(struct xen_blkif_ring *ring)
+__do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags)
 {
        union blkif_back_rings *blk_rings = &ring->blk_rings;
        struct blkif_request req;
                if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
                        break;
 
+               /* We've seen a request, so clear spurious eoi flag. */
+               *eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS;
+
                if (kthread_should_stop()) {
                        more_to_do = 1;
                        break;
 }
 
 static int
-do_block_io_op(struct xen_blkif_ring *ring)
+do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags)
 {
        union blkif_back_rings *blk_rings = &ring->blk_rings;
        int more_to_do;
 
        do {
-               more_to_do = __do_block_io_op(ring);
+               more_to_do = __do_block_io_op(ring, eoi_flags);
                if (more_to_do)
                        break;
 
 
                BUG();
        }
 
-       err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn,
-                                                   xen_blkif_be_int, 0,
-                                                   "blkif-backend", ring);
+       err = bind_interdomain_evtchn_to_irqhandler_lateeoi(blkif->domid,
+                       evtchn, xen_blkif_be_int, 0, "blkif-backend", ring);
        if (err < 0) {
                xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
                ring->blk_rings.common.sring = NULL;