From 551b0e9128d695919fca5829682f1156854328f1 Mon Sep 17 00:00:00 2001 From: Pawel Wodkowski Date: Wed, 9 Aug 2017 19:05:06 +0200 Subject: [PATCH] vhost: bring back interrupt suppressing hints Try to do the same as DPDK does: volatile write on used->idx and memory barier before reading avail->flags. Change-Id: Ibe4629a8228a02088913593ac9b32de56a60b062 Signed-off-by: Pawel Wodkowski Reviewed-on: https://review.gerrithub.io/373578 Reviewed-by: Jim Harris Tested-by: SPDK Automated Test System Reviewed-by: Changpeng Liu --- lib/vhost/vhost.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index 26c0a0512..3f2a3c8a0 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -37,6 +37,7 @@ #include "spdk/likely.h" #include "spdk/string.h" #include "spdk/util.h" +#include "spdk/barrier.h" #include "spdk/vhost.h" #include "vhost_internal.h" @@ -99,30 +100,31 @@ spdk_vhost_vq_used_ring_enqueue(struct spdk_vhost_dev *vdev, struct rte_vhost_vr uint16_t id, uint32_t len) { + int need_event = 0; struct vring_used *used = vq->used; - uint16_t size_mask = vq->size - 1; - uint16_t last_idx = vq->last_used_idx; + uint16_t last_idx = vq->last_used_idx & (vq->size - 1); SPDK_TRACELOG(SPDK_TRACE_VHOST_RING, "USED: last_idx=%"PRIu16" req id=%"PRIu16" len=%"PRIu32"\n", - last_idx, id, len); + vq->last_used_idx, id, len); vq->last_used_idx++; - last_idx &= size_mask; - used->ring[last_idx].id = id; used->ring[last_idx].len = len; - rte_compiler_barrier(); + spdk_wmb(); + * (volatile uint16_t *) &used->idx = vq->last_used_idx; - vq->used->idx = vq->last_used_idx; - - /* - * We should be able to used hints form guest but simply checking - * avail->flags prove to be unreliable. Till it is figured out how - * reliable use avail->flags value interrupts are always sent to guest. - */ - eventfd_write(vq->callfd, (eventfd_t)1); + if (spdk_vhost_dev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && + spdk_unlikely(vq->avail->idx == vq->last_avail_idx)) { + need_event = 1; + } else { + spdk_mb(); + need_event = !(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT); + } + if (need_event) { + eventfd_write(vq->callfd, (eventfd_t)1); + } } bool