}
 EXPORT_SYMBOL_GPL(virtqueue_enable_cb);
 
+bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
+{
+       struct vring_virtqueue *vq = to_vvq(_vq);
+       u16 bufs;
+
+       START_USE(vq);
+
+       /* We optimistically turn back on interrupts, then check if there was
+        * more to do. */
+       /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to
+        * either clear the flags bit or point the event index at the next
+        * entry. Always do both to keep code simple. */
+       vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
+       /* TODO: tune this threshold */
+       bufs = (u16)(vq->vring.avail->idx - vq->last_used_idx) * 3 / 4;
+       vring_used_event(&vq->vring) = vq->last_used_idx + bufs;
+       virtio_mb();
+       if (unlikely((u16)(vq->vring.used->idx - vq->last_used_idx) > bufs)) {
+               END_USE(vq);
+               return false;
+       }
+
+       END_USE(vq);
+       return true;
+}
+EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed);
+
 void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
 
  *     This re-enables callbacks; it returns "false" if there are pending
  *     buffers in the queue, to detect a possible race between the driver
  *     checking for more work, and enabling callbacks.
+ * virtqueue_enable_cb_delayed: restart callbacks after disable_cb.
+ *     vq: the struct virtqueue we're talking about.
+ *     This re-enables callbacks but hints to the other side to delay
+ *     interrupts until most of the available buffers have been processed;
+ *     it returns "false" if there are many pending buffers in the queue,
+ *     to detect a possible race between the driver checking for more work,
+ *     and enabling callbacks.
  * virtqueue_detach_unused_buf: detach first unused buffer
  *     vq: the struct virtqueue we're talking about.
  *     Returns NULL or the "data" token handed to add_buf
 
 bool virtqueue_enable_cb(struct virtqueue *vq);
 
+bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
+
 void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
 /**