Commit a3353ec3 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

netdevsim: move max vf config to dev

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: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1c401078
...@@ -57,81 +57,6 @@ static struct device_attribute nsim_bus_dev_numvfs_attr = ...@@ -57,81 +57,6 @@ static struct device_attribute nsim_bus_dev_numvfs_attr =
__ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show, __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
nsim_bus_dev_numvfs_store); 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 static ssize_t
new_port_store(struct device *dev, struct device_attribute *attr, new_port_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
......
...@@ -227,6 +227,70 @@ static const struct file_operations nsim_dev_trap_fa_cookie_fops = { ...@@ -227,6 +227,70 @@ static const struct file_operations nsim_dev_trap_fa_cookie_fops = {
.owner = THIS_MODULE, .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 = { static const struct file_operations nsim_dev_max_vfs_fops = {
.open = simple_open, .open = simple_open,
.read = nsim_bus_dev_max_vfs_read, .read = nsim_bus_dev_max_vfs_read,
......
...@@ -317,13 +317,6 @@ void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *fib_data); ...@@ -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, u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
enum nsim_resource_id res_id, bool max); 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) 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; return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_PF;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment