svn commit: r255109 - head/sys/dev/virtio

Bryan Venteicher bryanv at FreeBSD.org
Sun Sep 1 04:16:44 UTC 2013


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. */


More information about the svn-src-all mailing list