aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/netdevsim
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/netdevsim')
-rw-r--r--drivers/net/netdevsim/bus.c155
-rw-r--r--drivers/net/netdevsim/dev.c204
-rw-r--r--drivers/net/netdevsim/ethtool.c28
-rw-r--r--drivers/net/netdevsim/health.c32
-rw-r--r--drivers/net/netdevsim/netdev.c72
-rw-r--r--drivers/net/netdevsim/netdevsim.h57
6 files changed, 266 insertions, 282 deletions
diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c
index 29f5627d11e6..25cb2e600d53 100644
--- a/drivers/net/netdevsim/bus.c
+++ b/drivers/net/netdevsim/bus.c
@@ -8,7 +8,6 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mutex.h>
-#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
@@ -24,39 +23,6 @@ static struct nsim_bus_dev *to_nsim_bus_dev(struct device *dev)
return container_of(dev, struct nsim_bus_dev, dev);
}
-static int nsim_bus_dev_vfs_enable(struct nsim_bus_dev *nsim_bus_dev,
- unsigned int num_vfs)
-{
- struct nsim_dev *nsim_dev;
- int err = 0;
-
- if (nsim_bus_dev->max_vfs < num_vfs)
- return -ENOMEM;
-
- if (!nsim_bus_dev->vfconfigs)
- return -ENOMEM;
- nsim_bus_dev->num_vfs = num_vfs;
-
- nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
- if (nsim_esw_mode_is_switchdev(nsim_dev)) {
- err = nsim_esw_switchdev_enable(nsim_dev, NULL);
- if (err)
- nsim_bus_dev->num_vfs = 0;
- }
-
- return err;
-}
-
-void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev)
-{
- struct nsim_dev *nsim_dev;
-
- nsim_bus_dev->num_vfs = 0;
- nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
- if (nsim_esw_mode_is_switchdev(nsim_dev))
- nsim_esw_legacy_enable(nsim_dev, NULL);
-}
-
static ssize_t
nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -69,27 +35,13 @@ nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr,
if (ret)
return ret;
- mutex_lock(&nsim_bus_dev->vfs_lock);
- if (nsim_bus_dev->num_vfs == num_vfs)
- goto exit_good;
- if (nsim_bus_dev->num_vfs && num_vfs) {
- ret = -EBUSY;
- goto exit_unlock;
- }
-
- if (num_vfs) {
- ret = nsim_bus_dev_vfs_enable(nsim_bus_dev, num_vfs);
- if (ret)
- goto exit_unlock;
- } else {
- nsim_bus_dev_vfs_disable(nsim_bus_dev);
- }
-exit_good:
- ret = count;
-exit_unlock:
- mutex_unlock(&nsim_bus_dev->vfs_lock);
+ device_lock(dev);
+ ret = -ENOENT;
+ if (dev_get_drvdata(dev))
+ ret = nsim_drv_configure_vfs(nsim_bus_dev, num_vfs);
+ device_unlock(dev);
- return ret;
+ return ret ? ret : count;
}
static ssize_t
@@ -105,79 +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_bus_dev *nsim_bus_dev = file->private_data;
- 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_bus_dev *nsim_bus_dev = file->private_data;
- 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_bus_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_bus_dev->vfconfigs);
- nsim_bus_dev->vfconfigs = vfconfigs;
- nsim_bus_dev->max_vfs = val;
- *ppos += count;
- ret = count;
-unlock:
- mutex_unlock(&nsim_bus_dev->vfs_lock);
- return ret;
-}
-
static ssize_t
new_port_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -201,7 +80,7 @@ new_port_store(struct device *dev, struct device_attribute *attr,
return -EBUSY;
}
- ret = nsim_dev_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
+ ret = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
return ret ? ret : count;
}
@@ -231,7 +110,7 @@ del_port_store(struct device *dev, struct device_attribute *attr,
return -EBUSY;
}
- ret = nsim_dev_port_del(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
+ ret = nsim_drv_port_del(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
return ret ? ret : count;
}
@@ -371,14 +250,14 @@ static int nsim_bus_probe(struct device *dev)
{
struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
- return nsim_dev_probe(nsim_bus_dev);
+ return nsim_drv_probe(nsim_bus_dev);
}
static void nsim_bus_remove(struct device *dev)
{
struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
- nsim_dev_remove(nsim_bus_dev);
+ nsim_drv_remove(nsim_bus_dev);
}
static int nsim_num_vf(struct device *dev)
@@ -420,26 +299,15 @@ nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queu
nsim_bus_dev->initial_net = current->nsproxy->net_ns;
nsim_bus_dev->max_vfs = NSIM_BUS_DEV_MAX_VFS;
mutex_init(&nsim_bus_dev->nsim_bus_reload_lock);
- mutex_init(&nsim_bus_dev->vfs_lock);
/* Disallow using nsim_bus_dev */
smp_store_release(&nsim_bus_dev->init, false);
- nsim_bus_dev->vfconfigs = kcalloc(nsim_bus_dev->max_vfs,
- sizeof(struct nsim_vf_config),
- GFP_KERNEL | __GFP_NOWARN);
- if (!nsim_bus_dev->vfconfigs) {
- err = -ENOMEM;
- goto err_nsim_bus_dev_id_free;
- }
-
err = device_register(&nsim_bus_dev->dev);
if (err)
- goto err_nsim_vfs_free;
+ goto err_nsim_bus_dev_id_free;
return nsim_bus_dev;
-err_nsim_vfs_free:
- kfree(nsim_bus_dev->vfconfigs);
err_nsim_bus_dev_id_free:
ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
err_nsim_bus_dev_free:
@@ -453,7 +321,6 @@ static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev)
smp_store_release(&nsim_bus_dev->init, false);
device_unregister(&nsim_bus_dev->dev);
ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
- kfree(nsim_bus_dev->vfconfigs);
kfree(nsim_bus_dev);
}
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index 54313bd57797..54345c096a16 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -56,6 +56,22 @@ static inline unsigned int nsim_dev_port_index_to_vf_index(unsigned int port_ind
static struct dentry *nsim_dev_ddir;
+unsigned int nsim_dev_get_vfs(struct nsim_dev *nsim_dev)
+{
+ WARN_ON(!lockdep_rtnl_is_held() &&
+ !lockdep_is_held(&nsim_dev->vfs_lock));
+
+ return nsim_dev->nsim_bus_dev->num_vfs;
+}
+
+static void
+nsim_bus_dev_set_vfs(struct nsim_bus_dev *nsim_bus_dev, unsigned int num_vfs)
+{
+ rtnl_lock();
+ nsim_bus_dev->num_vfs = num_vfs;
+ rtnl_unlock();
+}
+
#define NSIM_DEV_DUMMY_REGION_SIZE (1024 * 32)
static int
@@ -211,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,
@@ -259,11 +339,9 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
debugfs_create_bool("fail_trap_policer_counter_get", 0600,
nsim_dev->ddir,
&nsim_dev->fail_trap_policer_counter_get);
- nsim_dev->max_vfs = debugfs_create_file("max_vfs",
- 0600,
- nsim_dev->ddir,
- nsim_dev->nsim_bus_dev,
- &nsim_dev_max_vfs_fops);
+ debugfs_create_file("max_vfs", 0600, nsim_dev->ddir,
+ nsim_dev, &nsim_dev_max_vfs_fops);
+
nsim_dev->nodes_ddir = debugfs_create_dir("rate_nodes", nsim_dev->ddir);
if (IS_ERR(nsim_dev->nodes_ddir)) {
err = PTR_ERR(nsim_dev->nodes_ddir);
@@ -328,9 +406,9 @@ static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev,
unsigned int vf_id = nsim_dev_port_index_to_vf_index(port_index);
debugfs_create_u16("tx_share", 0400, nsim_dev_port->ddir,
- &nsim_bus_dev->vfconfigs[vf_id].min_tx_rate);
+ &nsim_dev->vfconfigs[vf_id].min_tx_rate);
debugfs_create_u16("tx_max", 0400, nsim_dev_port->ddir,
- &nsim_bus_dev->vfconfigs[vf_id].max_tx_rate);
+ &nsim_dev->vfconfigs[vf_id].max_tx_rate);
nsim_dev_port->rate_parent = debugfs_create_file("rate_parent",
0400,
nsim_dev_port->ddir,
@@ -490,7 +568,9 @@ static void nsim_dev_dummy_region_exit(struct nsim_dev *nsim_dev)
}
static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port);
-int nsim_esw_legacy_enable(struct nsim_dev *nsim_dev, struct netlink_ext_ack *extack)
+
+static int nsim_esw_legacy_enable(struct nsim_dev *nsim_dev,
+ struct netlink_ext_ack *extack)
{
struct devlink *devlink = priv_to_devlink(nsim_dev);
struct nsim_dev_port *nsim_dev_port, *tmp;
@@ -505,13 +585,14 @@ int nsim_esw_legacy_enable(struct nsim_dev *nsim_dev, struct netlink_ext_ack *ex
return 0;
}
-int nsim_esw_switchdev_enable(struct nsim_dev *nsim_dev, struct netlink_ext_ack *extack)
+static int nsim_esw_switchdev_enable(struct nsim_dev *nsim_dev,
+ struct netlink_ext_ack *extack)
{
struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev;
int i, err;
- for (i = 0; i < nsim_bus_dev->num_vfs; i++) {
- err = nsim_dev_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_VF, i);
+ for (i = 0; i < nsim_dev_get_vfs(nsim_dev); i++) {
+ err = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_VF, i);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Failed to initialize VFs' netdevsim ports");
pr_err("Failed to initialize VF id=%d. %d.\n", i, err);
@@ -523,7 +604,7 @@ int nsim_esw_switchdev_enable(struct nsim_dev *nsim_dev, struct netlink_ext_ack
err_port_add_vfs:
for (i--; i >= 0; i--)
- nsim_dev_port_del(nsim_bus_dev, NSIM_DEV_PORT_TYPE_VF, i);
+ nsim_drv_port_del(nsim_bus_dev, NSIM_DEV_PORT_TYPE_VF, i);
return err;
}
@@ -533,7 +614,7 @@ static int nsim_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
struct nsim_dev *nsim_dev = devlink_priv(devlink);
int err = 0;
- mutex_lock(&nsim_dev->nsim_bus_dev->vfs_lock);
+ mutex_lock(&nsim_dev->vfs_lock);
if (mode == nsim_dev->esw_mode)
goto unlock;
@@ -545,7 +626,7 @@ static int nsim_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
err = -EINVAL;
unlock:
- mutex_unlock(&nsim_dev->nsim_bus_dev->vfs_lock);
+ mutex_unlock(&nsim_dev->vfs_lock);
return err;
}
@@ -1093,7 +1174,7 @@ static int nsim_leaf_tx_share_set(struct devlink_rate *devlink_rate, void *priv,
u64 tx_share, struct netlink_ext_ack *extack)
{
struct nsim_dev_port *nsim_dev_port = priv;
- struct nsim_bus_dev *nsim_bus_dev = nsim_dev_port->ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = nsim_dev_port->ns->nsim_dev;
int vf_id = nsim_dev_port_index_to_vf_index(nsim_dev_port->port_index);
int err;
@@ -1101,7 +1182,7 @@ static int nsim_leaf_tx_share_set(struct devlink_rate *devlink_rate, void *priv,
if (err)
return err;
- nsim_bus_dev->vfconfigs[vf_id].min_tx_rate = tx_share;
+ nsim_dev->vfconfigs[vf_id].min_tx_rate = tx_share;
return 0;
}
@@ -1109,7 +1190,7 @@ static int nsim_leaf_tx_max_set(struct devlink_rate *devlink_rate, void *priv,
u64 tx_max, struct netlink_ext_ack *extack)
{
struct nsim_dev_port *nsim_dev_port = priv;
- struct nsim_bus_dev *nsim_bus_dev = nsim_dev_port->ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = nsim_dev_port->ns->nsim_dev;
int vf_id = nsim_dev_port_index_to_vf_index(nsim_dev_port->port_index);
int err;
@@ -1117,7 +1198,7 @@ static int nsim_leaf_tx_max_set(struct devlink_rate *devlink_rate, void *priv,
if (err)
return err;
- nsim_bus_dev->vfconfigs[vf_id].max_tx_rate = tx_max;
+ nsim_dev->vfconfigs[vf_id].max_tx_rate = tx_max;
return 0;
}
@@ -1273,13 +1354,12 @@ static const struct devlink_ops nsim_dev_devlink_ops = {
static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type,
unsigned int port_index)
{
- struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev;
struct devlink_port_attrs attrs = {};
struct nsim_dev_port *nsim_dev_port;
struct devlink_port *devlink_port;
int err;
- if (type == NSIM_DEV_PORT_TYPE_VF && !nsim_bus_dev->num_vfs)
+ if (type == NSIM_DEV_PORT_TYPE_VF && !nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL);
@@ -1442,7 +1522,7 @@ err_dummy_region_exit:
return err;
}
-int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
+int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)
{
struct nsim_dev *nsim_dev;
struct devlink *devlink;
@@ -1457,6 +1537,7 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
INIT_LIST_HEAD(&nsim_dev->port_list);
+ mutex_init(&nsim_dev->vfs_lock);
mutex_init(&nsim_dev->port_list_lock);
nsim_dev->fw_update_status = true;
nsim_dev->fw_update_overwrite_mask = 0;
@@ -1466,13 +1547,17 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
- err = nsim_dev_resources_register(devlink);
- if (err)
+ nsim_dev->vfconfigs = kcalloc(nsim_bus_dev->max_vfs,
+ sizeof(struct nsim_vf_config),
+ GFP_KERNEL | __GFP_NOWARN);
+ if (!nsim_dev->vfconfigs) {
+ err = -ENOMEM;
goto err_devlink_free;
+ }
- err = devlink_register(devlink);
+ err = nsim_dev_resources_register(devlink);
if (err)
- goto err_resources_unregister;
+ goto err_vfc_free;
err = devlink_params_register(devlink, nsim_devlink_params,
ARRAY_SIZE(nsim_devlink_params));
@@ -1514,9 +1599,9 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
if (err)
goto err_psample_exit;
- devlink_params_publish(devlink);
- devlink_reload_enable(devlink);
nsim_dev->esw_mode = DEVLINK_ESWITCH_MODE_LEGACY;
+ devlink_set_features(devlink, DEVLINK_F_RELOAD);
+ devlink_register(devlink);
return 0;
err_psample_exit:
@@ -1537,11 +1622,12 @@ err_params_unregister:
devlink_params_unregister(devlink, nsim_devlink_params,
ARRAY_SIZE(nsim_devlink_params));
err_dl_unregister:
- devlink_unregister(devlink);
-err_resources_unregister:
devlink_resources_unregister(devlink, NULL);
+err_vfc_free:
+ kfree(nsim_dev->vfconfigs);
err_devlink_free:
devlink_free(devlink);
+ dev_set_drvdata(&nsim_bus_dev->dev, NULL);
return err;
}
@@ -1553,10 +1639,13 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
return;
debugfs_remove(nsim_dev->take_snapshot);
- mutex_lock(&nsim_dev->nsim_bus_dev->vfs_lock);
- if (nsim_dev->nsim_bus_dev->num_vfs)
- nsim_bus_dev_vfs_disable(nsim_dev->nsim_bus_dev);
- mutex_unlock(&nsim_dev->nsim_bus_dev->vfs_lock);
+ mutex_lock(&nsim_dev->vfs_lock);
+ if (nsim_dev_get_vfs(nsim_dev)) {
+ nsim_bus_dev_set_vfs(nsim_dev->nsim_bus_dev, 0);
+ if (nsim_esw_mode_is_switchdev(nsim_dev))
+ nsim_esw_legacy_enable(nsim_dev, NULL);
+ }
+ mutex_unlock(&nsim_dev->vfs_lock);
nsim_dev_port_del_all(nsim_dev);
nsim_dev_psample_exit(nsim_dev);
@@ -1567,22 +1656,22 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
mutex_destroy(&nsim_dev->port_list_lock);
}
-void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
+void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev)
{
struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
struct devlink *devlink = priv_to_devlink(nsim_dev);
- devlink_reload_disable(devlink);
-
+ devlink_unregister(devlink);
nsim_dev_reload_destroy(nsim_dev);
nsim_bpf_dev_exit(nsim_dev);
nsim_dev_debugfs_exit(nsim_dev);
devlink_params_unregister(devlink, nsim_devlink_params,
ARRAY_SIZE(nsim_devlink_params));
- devlink_unregister(devlink);
devlink_resources_unregister(devlink, NULL);
+ kfree(nsim_dev->vfconfigs);
devlink_free(devlink);
+ dev_set_drvdata(&nsim_bus_dev->dev, NULL);
}
static struct nsim_dev_port *
@@ -1598,7 +1687,7 @@ __nsim_dev_port_lookup(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type,
return NULL;
}
-int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type,
+int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type,
unsigned int port_index)
{
struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
@@ -1613,7 +1702,7 @@ int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type
return err;
}
-int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type,
+int nsim_drv_port_del(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type,
unsigned int port_index)
{
struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
@@ -1630,6 +1719,43 @@ int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type
return err;
}
+int nsim_drv_configure_vfs(struct nsim_bus_dev *nsim_bus_dev,
+ unsigned int num_vfs)
+{
+ struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
+ int ret = 0;
+
+ mutex_lock(&nsim_dev->vfs_lock);
+ if (nsim_bus_dev->num_vfs == num_vfs)
+ goto exit_unlock;
+ if (nsim_bus_dev->num_vfs && num_vfs) {
+ ret = -EBUSY;
+ goto exit_unlock;
+ }
+ if (nsim_bus_dev->max_vfs < num_vfs) {
+ ret = -ENOMEM;
+ goto exit_unlock;
+ }
+
+ nsim_bus_dev_set_vfs(nsim_bus_dev, num_vfs);
+ if (nsim_esw_mode_is_switchdev(nsim_dev)) {
+ if (num_vfs) {
+ ret = nsim_esw_switchdev_enable(nsim_dev, NULL);
+ if (ret) {
+ nsim_bus_dev_set_vfs(nsim_bus_dev, 0);
+ goto exit_unlock;
+ }
+ } else {
+ nsim_esw_legacy_enable(nsim_dev, NULL);
+ }
+ }
+
+exit_unlock:
+ mutex_unlock(&nsim_dev->vfs_lock);
+
+ return ret;
+}
+
int nsim_dev_init(void)
{
nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);
diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
index b03a0513eb7e..0ab6a40be611 100644
--- a/drivers/net/netdevsim/ethtool.c
+++ b/drivers/net/netdevsim/ethtool.c
@@ -81,6 +81,30 @@ static int nsim_set_ringparam(struct net_device *dev,
return 0;
}
+static void
+nsim_get_channels(struct net_device *dev, struct ethtool_channels *ch)
+{
+ struct netdevsim *ns = netdev_priv(dev);
+
+ ch->max_combined = ns->nsim_bus_dev->num_queues;
+ ch->combined_count = ns->ethtool.channels;
+}
+
+static int
+nsim_set_channels(struct net_device *dev, struct ethtool_channels *ch)
+{
+ struct netdevsim *ns = netdev_priv(dev);
+ int err;
+
+ err = netif_set_real_num_queues(dev, ch->combined_count,
+ ch->combined_count);
+ if (err)
+ return err;
+
+ ns->ethtool.channels = ch->combined_count;
+ return 0;
+}
+
static int
nsim_get_fecparam(struct net_device *dev, struct ethtool_fecparam *fecparam)
{
@@ -118,6 +142,8 @@ static const struct ethtool_ops nsim_ethtool_ops = {
.get_coalesce = nsim_get_coalesce,
.get_ringparam = nsim_get_ringparam,
.set_ringparam = nsim_set_ringparam,
+ .get_channels = nsim_get_channels,
+ .set_channels = nsim_set_channels,
.get_fecparam = nsim_get_fecparam,
.set_fecparam = nsim_set_fecparam,
};
@@ -141,6 +167,8 @@ void nsim_ethtool_init(struct netdevsim *ns)
ns->ethtool.fec.fec = ETHTOOL_FEC_NONE;
ns->ethtool.fec.active_fec = ETHTOOL_FEC_NONE;
+ ns->ethtool.channels = ns->nsim_bus_dev->num_queues;
+
ethtool = debugfs_create_dir("ethtool", ns->nsim_dev_port->ddir);
debugfs_create_u32("get_err", 0600, ethtool, &ns->ethtool.get_err);
diff --git a/drivers/net/netdevsim/health.c b/drivers/net/netdevsim/health.c
index 04aebdf85747..aa77af4a68df 100644
--- a/drivers/net/netdevsim/health.c
+++ b/drivers/net/netdevsim/health.c
@@ -110,26 +110,6 @@ static int nsim_dev_dummy_fmsg_put(struct devlink_fmsg *fmsg, u32 binary_len)
if (err)
return err;
- err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_bool_array");
- if (err)
- return err;
- for (i = 0; i < 10; i++) {
- err = devlink_fmsg_bool_put(fmsg, true);
- if (err)
- return err;
- }
- err = devlink_fmsg_arr_pair_nest_end(fmsg);
- if (err)
- return err;
-
- err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_u8_array");
- if (err)
- return err;
- for (i = 0; i < 10; i++) {
- err = devlink_fmsg_u8_put(fmsg, i);
- if (err)
- return err;
- }
err = devlink_fmsg_arr_pair_nest_end(fmsg);
if (err)
return err;
@@ -146,18 +126,6 @@ static int nsim_dev_dummy_fmsg_put(struct devlink_fmsg *fmsg, u32 binary_len)
if (err)
return err;
- err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_u64_array");
- if (err)
- return err;
- for (i = 0; i < 10; i++) {
- err = devlink_fmsg_u64_put(fmsg, i);
- if (err)
- return err;
- }
- err = devlink_fmsg_arr_pair_nest_end(fmsg);
- if (err)
- return err;
-
err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_array_of_objects");
if (err)
return err;
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 50572e0f1f52..e470e3398abc 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -82,12 +82,12 @@ nsim_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
static int nsim_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
{
struct netdevsim *ns = netdev_priv(dev);
- struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = ns->nsim_dev;
/* Only refuse multicast addresses, zero address can mean unset/any. */
- if (vf >= nsim_bus_dev->num_vfs || is_multicast_ether_addr(mac))
+ if (vf >= nsim_dev_get_vfs(nsim_dev) || is_multicast_ether_addr(mac))
return -EINVAL;
- memcpy(nsim_bus_dev->vfconfigs[vf].vf_mac, mac, ETH_ALEN);
+ memcpy(nsim_dev->vfconfigs[vf].vf_mac, mac, ETH_ALEN);
return 0;
}
@@ -96,14 +96,14 @@ static int nsim_set_vf_vlan(struct net_device *dev, int vf,
u16 vlan, u8 qos, __be16 vlan_proto)
{
struct netdevsim *ns = netdev_priv(dev);
- struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = ns->nsim_dev;
- if (vf >= nsim_bus_dev->num_vfs || vlan > 4095 || qos > 7)
+ if (vf >= nsim_dev_get_vfs(nsim_dev) || vlan > 4095 || qos > 7)
return -EINVAL;
- nsim_bus_dev->vfconfigs[vf].vlan = vlan;
- nsim_bus_dev->vfconfigs[vf].qos = qos;
- nsim_bus_dev->vfconfigs[vf].vlan_proto = vlan_proto;
+ nsim_dev->vfconfigs[vf].vlan = vlan;
+ nsim_dev->vfconfigs[vf].qos = qos;
+ nsim_dev->vfconfigs[vf].vlan_proto = vlan_proto;
return 0;
}
@@ -111,18 +111,18 @@ static int nsim_set_vf_vlan(struct net_device *dev, int vf,
static int nsim_set_vf_rate(struct net_device *dev, int vf, int min, int max)
{
struct netdevsim *ns = netdev_priv(dev);
- struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = ns->nsim_dev;
if (nsim_esw_mode_is_switchdev(ns->nsim_dev)) {
pr_err("Not supported in switchdev mode. Please use devlink API.\n");
return -EOPNOTSUPP;
}
- if (vf >= nsim_bus_dev->num_vfs)
+ if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
- nsim_bus_dev->vfconfigs[vf].min_tx_rate = min;
- nsim_bus_dev->vfconfigs[vf].max_tx_rate = max;
+ nsim_dev->vfconfigs[vf].min_tx_rate = min;
+ nsim_dev->vfconfigs[vf].max_tx_rate = max;
return 0;
}
@@ -130,11 +130,11 @@ static int nsim_set_vf_rate(struct net_device *dev, int vf, int min, int max)
static int nsim_set_vf_spoofchk(struct net_device *dev, int vf, bool val)
{
struct netdevsim *ns = netdev_priv(dev);
- struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = ns->nsim_dev;
- if (vf >= nsim_bus_dev->num_vfs)
+ if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
- nsim_bus_dev->vfconfigs[vf].spoofchk_enabled = val;
+ nsim_dev->vfconfigs[vf].spoofchk_enabled = val;
return 0;
}
@@ -142,11 +142,11 @@ static int nsim_set_vf_spoofchk(struct net_device *dev, int vf, bool val)
static int nsim_set_vf_rss_query_en(struct net_device *dev, int vf, bool val)
{
struct netdevsim *ns = netdev_priv(dev);
- struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = ns->nsim_dev;
- if (vf >= nsim_bus_dev->num_vfs)
+ if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
- nsim_bus_dev->vfconfigs[vf].rss_query_enabled = val;
+ nsim_dev->vfconfigs[vf].rss_query_enabled = val;
return 0;
}
@@ -154,11 +154,11 @@ static int nsim_set_vf_rss_query_en(struct net_device *dev, int vf, bool val)
static int nsim_set_vf_trust(struct net_device *dev, int vf, bool val)
{
struct netdevsim *ns = netdev_priv(dev);
- struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = ns->nsim_dev;
- if (vf >= nsim_bus_dev->num_vfs)
+ if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
- nsim_bus_dev->vfconfigs[vf].trusted = val;
+ nsim_dev->vfconfigs[vf].trusted = val;
return 0;
}
@@ -167,22 +167,22 @@ static int
nsim_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi)
{
struct netdevsim *ns = netdev_priv(dev);
- struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = ns->nsim_dev;
- if (vf >= nsim_bus_dev->num_vfs)
+ if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
ivi->vf = vf;
- ivi->linkstate = nsim_bus_dev->vfconfigs[vf].link_state;
- ivi->min_tx_rate = nsim_bus_dev->vfconfigs[vf].min_tx_rate;
- ivi->max_tx_rate = nsim_bus_dev->vfconfigs[vf].max_tx_rate;
- ivi->vlan = nsim_bus_dev->vfconfigs[vf].vlan;
- ivi->vlan_proto = nsim_bus_dev->vfconfigs[vf].vlan_proto;
- ivi->qos = nsim_bus_dev->vfconfigs[vf].qos;
- memcpy(&ivi->mac, nsim_bus_dev->vfconfigs[vf].vf_mac, ETH_ALEN);
- ivi->spoofchk = nsim_bus_dev->vfconfigs[vf].spoofchk_enabled;
- ivi->trusted = nsim_bus_dev->vfconfigs[vf].trusted;
- ivi->rss_query_en = nsim_bus_dev->vfconfigs[vf].rss_query_enabled;
+ ivi->linkstate = nsim_dev->vfconfigs[vf].link_state;
+ ivi->min_tx_rate = nsim_dev->vfconfigs[vf].min_tx_rate;
+ ivi->max_tx_rate = nsim_dev->vfconfigs[vf].max_tx_rate;
+ ivi->vlan = nsim_dev->vfconfigs[vf].vlan;
+ ivi->vlan_proto = nsim_dev->vfconfigs[vf].vlan_proto;
+ ivi->qos = nsim_dev->vfconfigs[vf].qos;
+ memcpy(&ivi->mac, nsim_dev->vfconfigs[vf].vf_mac, ETH_ALEN);
+ ivi->spoofchk = nsim_dev->vfconfigs[vf].spoofchk_enabled;
+ ivi->trusted = nsim_dev->vfconfigs[vf].trusted;
+ ivi->rss_query_en = nsim_dev->vfconfigs[vf].rss_query_enabled;
return 0;
}
@@ -190,9 +190,9 @@ nsim_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi)
static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state)
{
struct netdevsim *ns = netdev_priv(dev);
- struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev;
+ struct nsim_dev *nsim_dev = ns->nsim_dev;
- if (vf >= nsim_bus_dev->num_vfs)
+ if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
switch (state) {
@@ -204,7 +204,7 @@ static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state)
return -EINVAL;
}
- nsim_bus_dev->vfconfigs[vf].link_state = state;
+ nsim_dev->vfconfigs[vf].link_state = state;
return 0;
}
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 793c86dc5a9c..c49771f27f17 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -62,6 +62,7 @@ struct nsim_ethtool_pauseparam {
struct nsim_ethtool {
u32 get_err;
u32 set_err;
+ u32 channels;
struct nsim_ethtool_pauseparam pauseparam;
struct ethtool_coalesce coalesce;
struct ethtool_ringparam ring;
@@ -216,6 +217,19 @@ struct nsim_dev_port {
struct netdevsim *ns;
};
+struct nsim_vf_config {
+ int link_state;
+ u16 min_tx_rate;
+ u16 max_tx_rate;
+ u16 vlan;
+ __be16 vlan_proto;
+ u16 qos;
+ u8 vf_mac[ETH_ALEN];
+ bool spoofchk_enabled;
+ bool trusted;
+ bool rss_query_enabled;
+};
+
struct nsim_dev {
struct nsim_bus_dev *nsim_bus_dev;
struct nsim_fib_data *fib_data;
@@ -223,8 +237,11 @@ struct nsim_dev {
struct dentry *ddir;
struct dentry *ports_ddir;
struct dentry *take_snapshot;
- struct dentry *max_vfs;
struct dentry *nodes_ddir;
+
+ struct mutex vfs_lock; /* Protects vfconfigs */
+ struct nsim_vf_config *vfconfigs;
+
struct bpf_offload_dev *bpf_dev;
bool bpf_bind_accept;
bool bpf_bind_verifier_accept;
@@ -264,9 +281,6 @@ struct nsim_dev {
u16 esw_mode;
};
-int nsim_esw_legacy_enable(struct nsim_dev *nsim_dev, struct netlink_ext_ack *extack);
-int nsim_esw_switchdev_enable(struct nsim_dev *nsim_dev, struct netlink_ext_ack *extack);
-
static inline bool nsim_esw_mode_is_legacy(struct nsim_dev *nsim_dev)
{
return nsim_dev->esw_mode == DEVLINK_ESWITCH_MODE_LEGACY;
@@ -284,14 +298,18 @@ static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev)
int nsim_dev_init(void);
void nsim_dev_exit(void);
-int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev);
-void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev);
-int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
+int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev);
+void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev);
+int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev,
enum nsim_dev_port_type type,
unsigned int port_index);
-int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
+int nsim_drv_port_del(struct nsim_bus_dev *nsim_bus_dev,
enum nsim_dev_port_type type,
unsigned int port_index);
+int nsim_drv_configure_vfs(struct nsim_bus_dev *nsim_bus_dev,
+ unsigned int num_vfs);
+
+unsigned int nsim_dev_get_vfs(struct nsim_dev *nsim_dev);
struct nsim_fib_data *nsim_fib_create(struct devlink *devlink,
struct netlink_ext_ack *extack);
@@ -299,14 +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);
-void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev);
-
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;
@@ -335,19 +345,6 @@ static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb)
}
#endif
-struct nsim_vf_config {
- int link_state;
- u16 min_tx_rate;
- u16 max_tx_rate;
- u16 vlan;
- __be16 vlan_proto;
- u16 qos;
- u8 vf_mac[ETH_ALEN];
- bool spoofchk_enabled;
- bool trusted;
- bool rss_query_enabled;
-};
-
struct nsim_bus_dev {
struct device dev;
struct list_head list;
@@ -358,8 +355,6 @@ struct nsim_bus_dev {
*/
unsigned int max_vfs;
unsigned int num_vfs;
- struct mutex vfs_lock; /* Protects vfconfigs */
- struct nsim_vf_config *vfconfigs;
/* Lock for devlink->reload_enabled in netdevsim module */
struct mutex nsim_bus_reload_lock;
bool in_reload;