> -----Original Message-----
> From: Maxime Coquelin <maxime.coquelin@redhat.com>
> Sent: Wednesday, November 30, 2022 11:57 PM
> To: dev@dpdk.org; Xia, Chenbo <chenbo.xia@intel.com>;
> david.marchand@redhat.com; eperezma@redhat.com
> Cc: Maxime Coquelin <maxime.coquelin@redhat.com>
> Subject: [PATCH v1 15/21] net/virtio-user: get max number of queue pairs
> from device
>
> When supported by the backend (only vDPA for now), this
> patch gets the maximum number of queue pairs supported by
> the device by querying it in its config space.
>
> This is required for adding backend control queue support,
> as is index equals the maximum number of queues supported
> by the device as described by the Virtio specification.
>
> Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> ---
> .../net/virtio/virtio_user/virtio_user_dev.c | 93 ++++++++++++++-----
> drivers/net/virtio/virtio_user_ethdev.c | 7 --
> 2 files changed, 71 insertions(+), 29 deletions(-)
>
> 2.38.1
Reviewed-by: Chenbo Xia <chenbo.xia@intel.com>
@@ -253,6 +253,50 @@ int virtio_user_stop_device(struct virtio_user_dev *dev)
return -1;
}
+static int
+virtio_user_dev_init_max_queue_pairs(struct virtio_user_dev *dev, uint32_t user_max_qp)
+{
+ int ret;
+
+ if (!(dev->device_features & (1ULL << VIRTIO_NET_F_MQ))) {
+ dev->max_queue_pairs = 1;
+ return 0;
+ }
+
+ if (!dev->ops->get_config) {
+ dev->max_queue_pairs = user_max_qp;
+ return 0;
+ }
+
+ ret = dev->ops->get_config(dev, (uint8_t *)&dev->max_queue_pairs,
+ offsetof(struct virtio_net_config, max_virtqueue_pairs),
+ sizeof(uint16_t));
+ if (ret) {
+ /*
+ * We need to know the max queue pair from the device so that
+ * the control queue gets the right index.
+ */
+ dev->max_queue_pairs = 1;
+ PMD_DRV_LOG(ERR, "(%s) Failed to get max queue pairs from device", dev->path);
+
+ return ret;
+ }
+
+ if (dev->max_queue_pairs > VIRTIO_MAX_VIRTQUEUE_PAIRS) {
+ /*
+ * If the device supports control queue, the control queue
+ * index is max_virtqueue_pairs * 2. Disable MQ if it happens.
+ */
+ PMD_DRV_LOG(ERR, "(%s) Device advertises too many queues (%u, max supported %u)",
+ dev->path, dev->max_queue_pairs, VIRTIO_MAX_VIRTQUEUE_PAIRS);
+ dev->max_queue_pairs = 1;
+
+ return -1;
+ }
+
+ return 0;
+}
+
int
virtio_user_dev_set_mac(struct virtio_user_dev *dev)
{
@@ -511,24 +555,7 @@ virtio_user_dev_setup(struct virtio_user_dev *dev)
return -1;
}
- if (virtio_user_dev_init_notify(dev) < 0) {
- PMD_INIT_LOG(ERR, "(%s) Failed to init notifiers", dev->path);
- goto destroy;
- }
-
- if (virtio_user_fill_intr_handle(dev) < 0) {
- PMD_INIT_LOG(ERR, "(%s) Failed to init interrupt handler", dev->path);
- goto uninit;
- }
-
return 0;
-
-uninit:
- virtio_user_dev_uninit_notify(dev);
-destroy:
- dev->ops->destroy(dev);
-
- return -1;
}
/* Use below macro to filter features from vhost backend */
@@ -570,7 +597,6 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, uint16_t queues,
}
dev->started = 0;
- dev->max_queue_pairs = queues;
dev->queue_pairs = 1; /* mq disabled by default */
dev->queue_size = queue_size;
dev->is_server = server;
@@ -591,23 +617,39 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, uint16_t queues,
if (dev->ops->set_owner(dev) < 0) {
PMD_INIT_LOG(ERR, "(%s) Failed to set backend owner", dev->path);
- return -1;
+ goto destroy;
}
if (dev->ops->get_backend_features(&backend_features) < 0) {
PMD_INIT_LOG(ERR, "(%s) Failed to get backend features", dev->path);
- return -1;
+ goto destroy;
}
dev->unsupported_features = ~(VIRTIO_USER_SUPPORTED_FEATURES | backend_features);
if (dev->ops->get_features(dev, &dev->device_features) < 0) {
PMD_INIT_LOG(ERR, "(%s) Failed to get device features", dev->path);
- return -1;
+ goto destroy;
}
virtio_user_dev_init_mac(dev, mac);
+ if (virtio_user_dev_init_max_queue_pairs(dev, queues))
+ dev->unsupported_features |= (1ull << VIRTIO_NET_F_MQ);
+
+ if (dev->max_queue_pairs > 1)
+ cq = 1;
+
+ if (virtio_user_dev_init_notify(dev) < 0) {
+ PMD_INIT_LOG(ERR, "(%s) Failed to init notifiers", dev->path);
+ goto destroy;
+ }
+
+ if (virtio_user_fill_intr_handle(dev) < 0) {
+ PMD_INIT_LOG(ERR, "(%s) Failed to init interrupt handler", dev->path);
+ goto notify_uninit;
+ }
+
if (!mrg_rxbuf)
dev->unsupported_features |= (1ull << VIRTIO_NET_F_MRG_RXBUF);
@@ -651,11 +693,18 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, uint16_t queues,
if (rte_errno != ENOTSUP) {
PMD_INIT_LOG(ERR, "(%s) Failed to register mem event callback",
dev->path);
- return -1;
+ goto notify_uninit;
}
}
return 0;
+
+notify_uninit:
+ virtio_user_dev_uninit_notify(dev);
+destroy:
+ dev->ops->destroy(dev);
+
+ return -1;
}
void
@@ -595,8 +595,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *vdev)
VIRTIO_USER_ARG_CQ_NUM);
goto end;
}
- } else if (queues > 1) {
- cq = 1;
}
if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_PACKED_VQ) == 1) {
@@ -617,11 +615,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *vdev)
}
}
- if (queues > 1 && cq == 0) {
- PMD_INIT_LOG(ERR, "multi-q requires ctrl-q");
- goto end;
- }
-
if (queues > VIRTIO_MAX_VIRTQUEUE_PAIRS) {
PMD_INIT_LOG(ERR, "arg %s %" PRIu64 " exceeds the limit %u",
VIRTIO_USER_ARG_QUEUES_NUM, queues,