From 39276ee82c54b7411b37ddf32a97a58144f8b31a Mon Sep 17 00:00:00 2001 From: Jin Yu Date: Fri, 6 Dec 2019 20:45:41 +0800 Subject: [PATCH] vhost: negotiate the packed ring feature Add the packed ring support in spdk vhost. Negotiate packed ring feature when start device. Change-Id: Idef50a1426b6e38d789d8c6982a3ed7594e32cf5 Signed-off-by: Jin Yu Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/672 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Ben Walker Reviewed-by: Changpeng Liu --- lib/vhost/vhost.c | 53 +++++++++++++++++++++++++++++++++----- lib/vhost/vhost_internal.h | 14 +++++++++- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index b717a16dc4..d6b0e211af 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -880,9 +880,24 @@ _stop_session(struct spdk_vhost_session *vsession) for (i = 0; i < vsession->max_queues; i++) { q = &vsession->virtqueue[i]; + + /* vring.desc and vring.desc_packed are in a union struct + * so q->vring.desc can replace q->vring.desc_packed. + */ if (q->vring.desc == NULL) { continue; } + + /* Packed virtqueues support up to 2^15 entries each + * so left one bit can be used as wrap counter. + */ + if (q->packed.packed_ring) { + q->last_avail_idx = q->last_avail_idx | + ((uint16_t)q->packed.avail_phase << 15); + q->last_used_idx = q->last_used_idx | + ((uint16_t)q->packed.used_phase << 15); + } + rte_vhost_set_vring_base(vsession->vid, i, q->last_avail_idx, q->last_used_idx); } @@ -925,6 +940,7 @@ vhost_start_device_cb(int vid) struct spdk_vhost_session *vsession; int rc = -1; uint16_t i; + bool packed_ring; pthread_mutex_lock(&g_vhost_mutex); @@ -941,6 +957,13 @@ vhost_start_device_cb(int vid) goto out; } + if (vhost_get_negotiated_features(vid, &vsession->negotiated_features) != 0) { + SPDK_ERRLOG("vhost device %d: Failed to get negotiated driver features\n", vid); + goto out; + } + + packed_ring = ((vsession->negotiated_features & (1ULL << VIRTIO_F_RING_PACKED)) != 0); + vsession->max_queues = 0; memset(vsession->virtqueue, 0, sizeof(vsession->virtqueue)); for (i = 0; i < SPDK_VHOST_MAX_VQUEUES; i++) { @@ -953,6 +976,9 @@ vhost_start_device_cb(int vid) q->vring_idx = i; rte_vhost_get_vhost_ring_inflight(vid, i, &q->vring_inflight); + /* vring.desc and vring.desc_packed are in a union struct + * so q->vring.desc can replace q->vring.desc_packed. + */ if (q->vring.desc == NULL || q->vring.size == 0) { continue; } @@ -962,14 +988,24 @@ vhost_start_device_cb(int vid) continue; } - /* Disable I/O submission notifications, we'll be polling. */ - q->vring.used->flags = VRING_USED_F_NO_NOTIFY; - vsession->max_queues = i + 1; - } + if (packed_ring) { + /* Packed virtqueues support up to 2^15 entries each + * so left one bit can be used as wrap counter. + */ + q->packed.avail_phase = q->last_avail_idx >> 15; + q->last_avail_idx = q->last_avail_idx & 0x7FFF; + q->packed.used_phase = q->last_used_idx >> 15; + q->last_used_idx = q->last_used_idx & 0x7FFF; - if (vhost_get_negotiated_features(vid, &vsession->negotiated_features) != 0) { - SPDK_ERRLOG("vhost device %d: Failed to get negotiated driver features\n", vid); - goto out; + /* Disable I/O submission notifications, we'll be polling. */ + q->vring.device_event->flags = VRING_PACKED_EVENT_FLAG_DISABLE; + } else { + /* Disable I/O submission notifications, we'll be polling. */ + q->vring.used->flags = VRING_USED_F_NO_NOTIFY; + } + + q->packed.packed_ring = packed_ring; + vsession->max_queues = i + 1; } if (vhost_get_mem_table(vid, &vsession->mem) != 0) { @@ -989,6 +1025,9 @@ vhost_start_device_cb(int vid) for (i = 0; i < vsession->max_queues; i++) { struct spdk_vhost_virtqueue *q = &vsession->virtqueue[i]; + /* vring.desc and vring.desc_packed are in a union struct + * so q->vring.desc can replace q->vring.desc_packed. + */ if (q->vring.desc != NULL && q->vring.size > 0) { rte_vhost_vring_call(vsession->vid, q->vring_idx); } diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index 0f49742281..88d0074f7b 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -68,7 +68,6 @@ */ #define SPDK_VHOST_COALESCING_DELAY_BASE_US 0 - #define SPDK_VHOST_FEATURES ((1ULL << VHOST_F_LOG_ALL) | \ (1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \ (1ULL << VIRTIO_F_VERSION_1) | \ @@ -88,6 +87,19 @@ struct spdk_vhost_virtqueue { uint16_t last_avail_idx; uint16_t last_used_idx; + struct { + /* To mark a descriptor as available in packed ring + * Equal to avail_wrap_counter in spec. + */ + uint8_t avail_phase : 1; + /* To mark a descriptor as used in packed ring + * Equal to used_wrap_counter in spec. + */ + uint8_t used_phase : 1; + uint8_t padding : 5; + bool packed_ring : 1; + } packed; + void *tasks; /* Request count from last stats check */