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 <jin.yu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/672
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Jin Yu 2019-12-06 20:45:41 +08:00 committed by Changpeng Liu
parent 4d2e26d888
commit 39276ee82c
2 changed files with 59 additions and 8 deletions

View File

@ -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);
}

View File

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