summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Venteicher <bryanv@FreeBSD.org>2013-09-01 04:16:43 +0000
committerBryan Venteicher <bryanv@FreeBSD.org>2013-09-01 04:16:43 +0000
commitb619f40aec70cb1128b3576a57e5c118173f89ed (patch)
tree04428f70dac94ec59e4e25ed5c69c4687625024c
parente73151eb827122b6da662018d051ba8f58ef7e82 (diff)
Notes
-rw-r--r--sys/dev/virtio/virtqueue.c32
-rw-r--r--sys/dev/virtio/virtqueue.h12
2 files changed, 32 insertions, 12 deletions
diff --git a/sys/dev/virtio/virtqueue.c b/sys/dev/virtio/virtqueue.c
index a82426ea1b49..beff14c5ab7a 100644
--- a/sys/dev/virtio/virtqueue.c
+++ b/sys/dev/virtio/virtqueue.c
@@ -127,7 +127,7 @@ static uint16_t vq_ring_enqueue_segments(struct virtqueue *,
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 *vq)
}
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;
}
diff --git a/sys/dev/virtio/virtqueue.h b/sys/dev/virtio/virtqueue.h
index 128a10a79e26..0d4ed9468d22 100644
--- a/sys/dev/virtio/virtqueue.h
+++ b/sys/dev/virtio/virtqueue.h
@@ -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 *vq, uint16_t size);
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. */