vdpa: Allow to configure max data virtqueues
authorEli Cohen <elic@nvidia.com>
Wed, 5 Jan 2022 11:46:37 +0000 (13:46 +0200)
committerMichael S. Tsirkin <mst@redhat.com>
Fri, 14 Jan 2022 23:50:53 +0000 (18:50 -0500)
Add netlink support to configure the max virtqueue pairs for a device.
At least one pair is required. The maximum is dictated by the device.

Example:
$ vdpa dev add name vdpa-a mgmtdev auxiliary/mlx5_core.sf.1 max_vqp 4

Signed-off-by: Eli Cohen <elic@nvidia.com>
Link: https://lore.kernel.org/r/20220105114646.577224-6-elic@nvidia.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
drivers/vdpa/vdpa.c
drivers/vhost/vdpa.c
drivers/virtio/virtio_vdpa.c
include/linux/vdpa.h

index 4494325..96d31b8 100644 (file)
@@ -404,7 +404,7 @@ static void vdpa_get_config_unlocked(struct vdpa_device *vdev,
         * If it does happen we assume a legacy guest.
         */
        if (!vdev->features_valid)
-               vdpa_set_features(vdev, 0);
+               vdpa_set_features(vdev, 0, true);
        ops->get_config(vdev, offset, buf, len);
 }
 
@@ -581,7 +581,8 @@ out:
 }
 
 #define VDPA_DEV_NET_ATTRS_MASK ((1 << VDPA_ATTR_DEV_NET_CFG_MACADDR) | \
-                                (1 << VDPA_ATTR_DEV_NET_CFG_MTU))
+                                (1 << VDPA_ATTR_DEV_NET_CFG_MTU) | \
+                                (1 << VDPA_ATTR_DEV_NET_CFG_MAX_VQP))
 
 static int vdpa_nl_cmd_dev_add_set_doit(struct sk_buff *skb, struct genl_info *info)
 {
@@ -607,6 +608,16 @@ static int vdpa_nl_cmd_dev_add_set_doit(struct sk_buff *skb, struct genl_info *i
                        nla_get_u16(nl_attrs[VDPA_ATTR_DEV_NET_CFG_MTU]);
                config.mask |= (1 << VDPA_ATTR_DEV_NET_CFG_MTU);
        }
+       if (nl_attrs[VDPA_ATTR_DEV_NET_CFG_MAX_VQP]) {
+               config.net.max_vq_pairs =
+                       nla_get_u16(nl_attrs[VDPA_ATTR_DEV_NET_CFG_MAX_VQP]);
+               if (!config.net.max_vq_pairs) {
+                       NL_SET_ERR_MSG_MOD(info->extack,
+                                          "At least one pair of VQs is required");
+                       return -EINVAL;
+               }
+               config.mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP);
+       }
 
        /* Skip checking capability if user didn't prefer to configure any
         * device networking attributes. It is likely that user might have used
index 293c51f..6e7edaf 100644 (file)
@@ -285,7 +285,7 @@ static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep)
        if (copy_from_user(&features, featurep, sizeof(features)))
                return -EFAULT;
 
-       if (vdpa_set_features(vdpa, features))
+       if (vdpa_set_features(vdpa, features, false))
                return -EINVAL;
 
        return 0;
index 7650455..7767a7f 100644 (file)
@@ -317,7 +317,7 @@ static int virtio_vdpa_finalize_features(struct virtio_device *vdev)
        /* Give virtio_ring a chance to accept features. */
        vring_transport_features(vdev);
 
-       return vdpa_set_features(vdpa, vdev->features);
+       return vdpa_set_features(vdpa, vdev->features, false);
 }
 
 static const char *virtio_vdpa_bus_name(struct virtio_device *vdev)
index ae047fa..6d4d7e4 100644 (file)
@@ -101,6 +101,7 @@ struct vdpa_dev_set_config {
        struct {
                u8 mac[ETH_ALEN];
                u16 mtu;
+               u16 max_vq_pairs;
        } net;
        u64 mask;
 };
@@ -391,17 +392,29 @@ static inline struct device *vdpa_get_dma_dev(struct vdpa_device *vdev)
 static inline int vdpa_reset(struct vdpa_device *vdev)
 {
        const struct vdpa_config_ops *ops = vdev->config;
+       int ret;
 
+       mutex_lock(&vdev->cf_mutex);
        vdev->features_valid = false;
-       return ops->reset(vdev);
+       ret = ops->reset(vdev);
+       mutex_unlock(&vdev->cf_mutex);
+       return ret;
 }
 
-static inline int vdpa_set_features(struct vdpa_device *vdev, u64 features)
+static inline int vdpa_set_features(struct vdpa_device *vdev, u64 features, bool locked)
 {
        const struct vdpa_config_ops *ops = vdev->config;
+       int ret;
+
+       if (!locked)
+               mutex_lock(&vdev->cf_mutex);
 
        vdev->features_valid = true;
-       return ops->set_driver_features(vdev, features);
+       ret = ops->set_driver_features(vdev, features);
+       if (!locked)
+               mutex_unlock(&vdev->cf_mutex);
+
+       return ret;
 }
 
 void vdpa_get_config(struct vdpa_device *vdev, unsigned int offset,