Author: bryanv
Date: Sun Sep  1 04:16:43 2013
New Revision: 255109
URL: http://svnweb.freebsd.org/changeset/base/255109

Log:
  Add support for postponing VirtIO virtqueue interrupts
  
  Partial support for the EVENT_IDX feature was added a while ago,
  but this commit adds an interface for the device driver to hint
  how long (in terms of descriptors) the next interrupt should be
  delayed.
  
  The first user of this will be used to reduce VirtIO net's Tx
  completion interrupts.

Modified:
  head/sys/dev/virtio/virtqueue.c
  head/sys/dev/virtio/virtqueue.h

Modified: head/sys/dev/virtio/virtqueue.c
==============================================================================
--- head/sys/dev/virtio/virtqueue.c     Sat Aug 31 22:32:42 2013        
(r255108)
+++ head/sys/dev/virtio/virtqueue.c     Sun Sep  1 04:16:43 2013        
(r255109)
@@ -127,7 +127,7 @@ static uint16_t     vq_ring_enqueue_segments
 static int     vq_ring_use_indirect(struct virtqueue *, int);
 static void    vq_ring_enqueue_indirect(struct virtqueue *, void *,
                    struct sglist *, int, int);
-static int     vq_ring_enable_interrupt(struct virtqueue *, uint16_t);
+static int     vq_ring_enable_interrupt(struct virtqueue *, uint16_t);
 static int     vq_ring_must_notify_host(struct virtqueue *);
 static void    vq_ring_notify_host(struct virtqueue *);
 static void    vq_ring_free_chain(struct virtqueue *, uint16_t);
@@ -440,28 +440,38 @@ virtqueue_enable_intr(struct virtqueue *
 }
 
 int
-virtqueue_postpone_intr(struct virtqueue *vq)
+virtqueue_postpone_intr(struct virtqueue *vq, vq_postpone_t hint)
 {
        uint16_t ndesc, avail_idx;
 
-       /*
-        * Request the next interrupt be postponed until at least half
-        * of the available descriptors have been consumed.
-        */
        avail_idx = vq->vq_ring.avail->idx;
-       ndesc = (uint16_t)(avail_idx - vq->vq_used_cons_idx) / 2;
+       ndesc = (uint16_t)(avail_idx - vq->vq_used_cons_idx);
+
+       switch (hint) {
+       case VQ_POSTPONE_SHORT:
+               ndesc /= 4;
+               break;
+       case VQ_POSTPONE_LONG:
+               ndesc *= 3 / 4;
+               break;
+       case VQ_POSTPONE_EMPTIED:
+               break;
+       }
 
        return (vq_ring_enable_interrupt(vq, ndesc));
 }
 
+/*
+ * Note this is only considered a hint to the host.
+ */
 void
 virtqueue_disable_intr(struct virtqueue *vq)
 {
 
-       /*
-        * Note this is only considered a hint to the host.
-        */
-       if ((vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) == 0)
+       if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) {
+               vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx -
+                   vq->vq_nentries - 1;
+       } else
                vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
 }
 

Modified: head/sys/dev/virtio/virtqueue.h
==============================================================================
--- head/sys/dev/virtio/virtqueue.h     Sat Aug 31 22:32:42 2013        
(r255108)
+++ head/sys/dev/virtio/virtqueue.h     Sun Sep  1 04:16:43 2013        
(r255109)
@@ -41,6 +41,16 @@ struct sglist;
 /* Device callback for a virtqueue interrupt. */
 typedef void virtqueue_intr_t(void *);
 
+/*
+ * Hint on how long the next interrupt should be postponed. This is
+ * only used when the EVENT_IDX feature is negotiated.
+ */
+typedef enum {
+       VQ_POSTPONE_SHORT,
+       VQ_POSTPONE_LONG,
+       VQ_POSTPONE_EMPTIED     /* Until all available desc are used. */
+} vq_postpone_t;
+
 #define VIRTQUEUE_MAX_NAME_SZ  32
 
 /* One for each virtqueue the device wishes to allocate. */
@@ -73,7 +83,7 @@ int    virtqueue_reinit(struct virtqueue *
 int     virtqueue_intr_filter(struct virtqueue *vq);
 void    virtqueue_intr(struct virtqueue *vq);
 int     virtqueue_enable_intr(struct virtqueue *vq);
-int     virtqueue_postpone_intr(struct virtqueue *vq);
+int     virtqueue_postpone_intr(struct virtqueue *vq, vq_postpone_t hint);
 void    virtqueue_disable_intr(struct virtqueue *vq);
 
 /* Get physical address of the virtqueue ring. */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to