diff --git a/include/spdk_internal/virtio.h b/include/spdk_internal/virtio.h index 7ccfb2f25fd..94eaf0a1cd8 100644 --- a/include/spdk_internal/virtio.h +++ b/include/spdk_internal/virtio.h @@ -48,6 +48,10 @@ #include "spdk/pci_ids.h" #include "spdk/env.h" +#ifndef VHOST_USER_F_PROTOCOL_FEATURES +#define VHOST_USER_F_PROTOCOL_FEATURES 30 +#endif + /** * The maximum virtqueue size is 2^15. Use that value as the end of * descriptor chain terminator since it will never be a valid index diff --git a/lib/bdev/virtio/bdev_virtio_blk.c b/lib/bdev/virtio/bdev_virtio_blk.c index 1b24e6bb764..76a774cbcd0 100644 --- a/lib/bdev/virtio/bdev_virtio_blk.c +++ b/lib/bdev/virtio/bdev_virtio_blk.c @@ -80,7 +80,8 @@ struct bdev_virtio_blk_io_channel { 1ULL << VIRTIO_BLK_F_TOPOLOGY | \ 1ULL << VIRTIO_BLK_F_MQ | \ 1ULL << VIRTIO_BLK_F_RO | \ - 1ULL << VIRTIO_RING_F_EVENT_IDX) + 1ULL << VIRTIO_RING_F_EVENT_IDX | \ + 1ULL << VHOST_USER_F_PROTOCOL_FEATURES) static int bdev_virtio_initialize(void); static int bdev_virtio_blk_get_ctx_size(void); diff --git a/lib/bdev/virtio/bdev_virtio_scsi.c b/lib/bdev/virtio/bdev_virtio_scsi.c index b0584a61630..f10577ca519 100644 --- a/lib/bdev/virtio/bdev_virtio_scsi.c +++ b/lib/bdev/virtio/bdev_virtio_scsi.c @@ -193,7 +193,8 @@ static bool g_bdev_virtio_finish = false; #define VIRTIO_SCSI_DEV_SUPPORTED_FEATURES \ (1ULL << VIRTIO_SCSI_F_INOUT | \ 1ULL << VIRTIO_SCSI_F_HOTPLUG | \ - 1ULL << VIRTIO_RING_F_EVENT_IDX) + 1ULL << VIRTIO_RING_F_EVENT_IDX | \ + 1ULL << VHOST_USER_F_PROTOCOL_FEATURES) static void virtio_scsi_dev_unregister_cb(void *io_device); static void virtio_scsi_dev_remove(struct virtio_scsi_dev *svdev, diff --git a/lib/virtio/virtio_user.c b/lib/virtio/virtio_user.c index a45d36ca0d5..e7fc65a8a7c 100644 --- a/lib/virtio/virtio_user.c +++ b/lib/virtio/virtio_user.c @@ -46,6 +46,9 @@ #include "spdk_internal/virtio.h" +#define VIRTIO_USER_SUPPORTED_PROTOCOL_FEATURES \ + (0) + static int virtio_user_create_queue(struct virtio_dev *vdev, uint32_t queue_sel) { @@ -286,6 +289,7 @@ static int virtio_user_set_features(struct virtio_dev *vdev, uint64_t features) { struct virtio_user_dev *dev = vdev->ctx; + uint64_t protocol_features; int ret; ret = dev->ops->send_request(dev, VHOST_USER_SET_FEATURES, &features); @@ -296,6 +300,23 @@ virtio_user_set_features(struct virtio_dev *vdev, uint64_t features) vdev->negotiated_features = features; vdev->modern = virtio_dev_has_feature(vdev, VIRTIO_F_VERSION_1); + if (!virtio_dev_has_feature(vdev, VHOST_USER_F_PROTOCOL_FEATURES)) { + /* nothing else to do */ + return 0; + } + + ret = dev->ops->send_request(dev, VHOST_USER_GET_PROTOCOL_FEATURES, &protocol_features); + if (ret < 0) { + return -1; + } + + protocol_features &= VIRTIO_USER_SUPPORTED_PROTOCOL_FEATURES; + ret = dev->ops->send_request(dev, VHOST_USER_SET_PROTOCOL_FEATURES, &protocol_features); + if (ret < 0) { + return -1; + } + + dev->protocol_features = protocol_features; return 0; } @@ -312,6 +333,7 @@ static int virtio_user_setup_queue(struct virtio_dev *vdev, struct virtqueue *vq) { struct virtio_user_dev *dev = vdev->ctx; + struct vhost_vring_state state; uint16_t queue_idx = vq->vq_queue_index; uint64_t desc_addr, avail_addr, used_addr; int callfd; @@ -339,6 +361,16 @@ virtio_user_setup_queue(struct virtio_dev *vdev, struct virtqueue *vq) return -1; } + state.index = vq->vq_queue_index; + state.num = 0; + + if (virtio_dev_has_feature(vdev, VHOST_USER_F_PROTOCOL_FEATURES) && + dev->ops->send_request(dev, VHOST_USER_SET_VRING_ENABLE, &state) < 0) { + SPDK_ERRLOG("failed to send VHOST_USER_SET_VRING_ENABLE: %s\n", + spdk_strerror(errno)); + return -1; + } + dev->callfds[queue_idx] = callfd; dev->kickfds[queue_idx] = kickfd; diff --git a/lib/virtio/virtio_user/vhost.h b/lib/virtio/virtio_user/vhost.h index bb8879ecdf8..69bedb177bd 100644 --- a/lib/virtio/virtio_user/vhost.h +++ b/lib/virtio/virtio_user/vhost.h @@ -79,6 +79,7 @@ struct virtio_user_dev { uint8_t status; char path[PATH_MAX]; + uint64_t protocol_features; struct vring vrings[SPDK_VIRTIO_MAX_VIRTQUEUES]; struct virtio_user_backend_ops *ops; }; diff --git a/lib/virtio/virtio_user/vhost_user.c b/lib/virtio/virtio_user/vhost_user.c index 5ae80bac29c..bd7714d98c3 100644 --- a/lib/virtio/virtio_user/vhost_user.c +++ b/lib/virtio/virtio_user/vhost_user.c @@ -314,12 +314,14 @@ vhost_user_sock(struct virtio_user_dev *dev, switch (req) { case VHOST_USER_GET_FEATURES: + case VHOST_USER_GET_PROTOCOL_FEATURES: case VHOST_USER_GET_QUEUE_NUM: need_reply = 1; break; case VHOST_USER_SET_FEATURES: case VHOST_USER_SET_LOG_BASE: + case VHOST_USER_SET_PROTOCOL_FEATURES: msg.payload.u64 = *((__u64 *)arg); msg.size = sizeof(msg.payload.u64); break; @@ -414,6 +416,7 @@ vhost_user_sock(struct virtio_user_dev *dev, switch (req) { case VHOST_USER_GET_FEATURES: + case VHOST_USER_GET_PROTOCOL_FEATURES: case VHOST_USER_GET_QUEUE_NUM: if (msg.size != sizeof(msg.payload.u64)) { SPDK_WARNLOG("Received bad msg size\n");