netdevsim: move max vf config to dev
authorJakub Kicinski <kuba@kernel.org>
Sat, 30 Oct 2021 23:15:04 +0000 (16:15 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 1 Nov 2021 13:29:41 +0000 (13:29 +0000)
max_vfs is a strange little beast because the file
hangs off of nsim's debugfs, but it configures a field
in the bus device. Move it to dev.c, let's look at it
as if the device driver was imposing VF limit based
on FW info (like pci_sriov_set_totalvfs()).

Again, when moving refactor the function not to hold
the vfs lock pointlessly while parsing the input.
Wrap the access from the read side in READ_ONCE()
to appease concurrency checkers. Do not check if
return value from snprintf() is negative...

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/netdevsim/bus.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/netdevsim.h

index d037600..0b41f16 100644 (file)
@@ -57,81 +57,6 @@ static struct device_attribute nsim_bus_dev_numvfs_attr =
        __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
               nsim_bus_dev_numvfs_store);
 
-ssize_t nsim_bus_dev_max_vfs_read(struct file *file,
-                                 char __user *data,
-                                 size_t count, loff_t *ppos)
-{
-       struct nsim_dev *nsim_dev = file->private_data;
-       struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev;
-       char buf[11];
-       ssize_t len;
-
-       len = snprintf(buf, sizeof(buf), "%u\n", nsim_bus_dev->max_vfs);
-       if (len < 0)
-               return len;
-
-       return simple_read_from_buffer(data, count, ppos, buf, len);
-}
-
-ssize_t nsim_bus_dev_max_vfs_write(struct file *file,
-                                  const char __user *data,
-                                  size_t count, loff_t *ppos)
-{
-       struct nsim_dev *nsim_dev = file->private_data;
-       struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev;
-       struct nsim_vf_config *vfconfigs;
-       ssize_t ret;
-       char buf[10];
-       u32 val;
-
-       if (*ppos != 0)
-               return 0;
-
-       if (count >= sizeof(buf))
-               return -ENOSPC;
-
-       mutex_lock(&nsim_dev->vfs_lock);
-       /* Reject if VFs are configured */
-       if (nsim_bus_dev->num_vfs) {
-               ret = -EBUSY;
-               goto unlock;
-       }
-
-       ret = copy_from_user(buf, data, count);
-       if (ret) {
-               ret = -EFAULT;
-               goto unlock;
-       }
-
-       buf[count] = '\0';
-       ret = kstrtouint(buf, 10, &val);
-       if (ret) {
-               ret = -EIO;
-               goto unlock;
-       }
-
-       /* max_vfs limited by the maximum number of provided port indexes */
-       if (val > NSIM_DEV_VF_PORT_INDEX_MAX - NSIM_DEV_VF_PORT_INDEX_BASE) {
-               ret = -ERANGE;
-               goto unlock;
-       }
-
-       vfconfigs = kcalloc(val, sizeof(struct nsim_vf_config), GFP_KERNEL | __GFP_NOWARN);
-       if (!vfconfigs) {
-               ret = -ENOMEM;
-               goto unlock;
-       }
-
-       kfree(nsim_dev->vfconfigs);
-       nsim_dev->vfconfigs = vfconfigs;
-       nsim_bus_dev->max_vfs = val;
-       *ppos += count;
-       ret = count;
-unlock:
-       mutex_unlock(&nsim_dev->vfs_lock);
-       return ret;
-}
-
 static ssize_t
 new_port_store(struct device *dev, struct device_attribute *attr,
               const char *buf, size_t count)
index c19f36c..040531f 100644 (file)
@@ -227,6 +227,70 @@ static const struct file_operations nsim_dev_trap_fa_cookie_fops = {
        .owner = THIS_MODULE,
 };
 
+static ssize_t nsim_bus_dev_max_vfs_read(struct file *file, char __user *data,
+                                        size_t count, loff_t *ppos)
+{
+       struct nsim_dev *nsim_dev = file->private_data;
+       char buf[11];
+       ssize_t len;
+
+       len = scnprintf(buf, sizeof(buf), "%u\n",
+                       READ_ONCE(nsim_dev->nsim_bus_dev->max_vfs));
+
+       return simple_read_from_buffer(data, count, ppos, buf, len);
+}
+
+static ssize_t nsim_bus_dev_max_vfs_write(struct file *file,
+                                         const char __user *data,
+                                         size_t count, loff_t *ppos)
+{
+       struct nsim_vf_config *vfconfigs;
+       struct nsim_dev *nsim_dev;
+       char buf[10];
+       ssize_t ret;
+       u32 val;
+
+       if (*ppos != 0)
+               return 0;
+
+       if (count >= sizeof(buf))
+               return -ENOSPC;
+
+       ret = copy_from_user(buf, data, count);
+       if (ret)
+               return -EFAULT;
+       buf[count] = '\0';
+
+       ret = kstrtouint(buf, 10, &val);
+       if (ret)
+               return -EINVAL;
+
+       /* max_vfs limited by the maximum number of provided port indexes */
+       if (val > NSIM_DEV_VF_PORT_INDEX_MAX - NSIM_DEV_VF_PORT_INDEX_BASE)
+               return -ERANGE;
+
+       vfconfigs = kcalloc(val, sizeof(struct nsim_vf_config),
+                           GFP_KERNEL | __GFP_NOWARN);
+       if (!vfconfigs)
+               return -ENOMEM;
+
+       nsim_dev = file->private_data;
+       mutex_lock(&nsim_dev->vfs_lock);
+       /* Reject if VFs are configured */
+       if (nsim_dev_get_vfs(nsim_dev)) {
+               ret = -EBUSY;
+       } else {
+               swap(nsim_dev->vfconfigs, vfconfigs);
+               WRITE_ONCE(nsim_dev->nsim_bus_dev->max_vfs, val);
+               *ppos += count;
+               ret = count;
+       }
+       mutex_unlock(&nsim_dev->vfs_lock);
+
+       kfree(vfconfigs);
+       return ret;
+}
+
 static const struct file_operations nsim_dev_max_vfs_fops = {
        .open = simple_open,
        .read = nsim_bus_dev_max_vfs_read,
index 8da5f82..fd71334 100644 (file)
@@ -317,13 +317,6 @@ void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *fib_data);
 u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
                     enum nsim_resource_id res_id, bool max);
 
-ssize_t nsim_bus_dev_max_vfs_read(struct file *file,
-                                 char __user *data,
-                                 size_t count, loff_t *ppos);
-ssize_t nsim_bus_dev_max_vfs_write(struct file *file,
-                                  const char __user *data,
-                                  size_t count, loff_t *ppos);
-
 static inline bool nsim_dev_port_is_pf(struct nsim_dev_port *nsim_dev_port)
 {
        return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_PF;