forked from mirrors/linux
		
	netdevsim: move device registration and related code to bus.c
Move netdevsim device registration into bus.c and alongside with that the related sysfs attributes. Introduce new struct nsim_bus_dev to represent a netdevsim device on netdevsim bus. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									925f5afedb
								
							
						
					
					
						commit
						40e4fe4ce1
					
				
					 4 changed files with 207 additions and 163 deletions
				
			
		| 
						 | 
				
			
			@ -4,15 +4,155 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/rtnetlink.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/sysfs.h>
 | 
			
		||||
 | 
			
		||||
#include "netdevsim.h"
 | 
			
		||||
 | 
			
		||||
struct bus_type nsim_bus = {
 | 
			
		||||
static u32 nsim_bus_dev_id;
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	nsim_bus_dev->vfconfigs = kcalloc(num_vfs,
 | 
			
		||||
					  sizeof(struct nsim_vf_config),
 | 
			
		||||
					  GFP_KERNEL);
 | 
			
		||||
	if (!nsim_bus_dev->vfconfigs)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	nsim_bus_dev->num_vfs = num_vfs;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev)
 | 
			
		||||
{
 | 
			
		||||
	kfree(nsim_bus_dev->vfconfigs);
 | 
			
		||||
	nsim_bus_dev->vfconfigs = NULL;
 | 
			
		||||
	nsim_bus_dev->num_vfs = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t
 | 
			
		||||
nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr,
 | 
			
		||||
			  const char *buf, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 | 
			
		||||
	unsigned int num_vfs;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = kstrtouint(buf, 0, &num_vfs);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	rtnl_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:
 | 
			
		||||
	rtnl_unlock();
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t
 | 
			
		||||
nsim_bus_dev_numvfs_show(struct device *dev,
 | 
			
		||||
			 struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 | 
			
		||||
 | 
			
		||||
	return sprintf(buf, "%u\n", nsim_bus_dev->num_vfs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct device_attribute nsim_bus_dev_numvfs_attr =
 | 
			
		||||
	__ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
 | 
			
		||||
	       nsim_bus_dev_numvfs_store);
 | 
			
		||||
 | 
			
		||||
static struct attribute *nsim_bus_dev_attrs[] = {
 | 
			
		||||
	&nsim_bus_dev_numvfs_attr.attr,
 | 
			
		||||
	NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct attribute_group nsim_bus_dev_attr_group = {
 | 
			
		||||
	.attrs = nsim_bus_dev_attrs,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct attribute_group *nsim_bus_dev_attr_groups[] = {
 | 
			
		||||
	&nsim_bus_dev_attr_group,
 | 
			
		||||
	NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void nsim_bus_dev_release(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 | 
			
		||||
 | 
			
		||||
	nsim_bus_dev_vfs_disable(nsim_bus_dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct device_type nsim_bus_dev_type = {
 | 
			
		||||
	.groups = nsim_bus_dev_attr_groups,
 | 
			
		||||
	.release = nsim_bus_dev_release,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int nsim_num_vf(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 | 
			
		||||
 | 
			
		||||
	return nsim_bus_dev->num_vfs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct bus_type nsim_bus = {
 | 
			
		||||
	.name		= DRV_NAME,
 | 
			
		||||
	.dev_name	= DRV_NAME,
 | 
			
		||||
	.num_vf		= nsim_num_vf,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct nsim_bus_dev *nsim_bus_dev_new(void)
 | 
			
		||||
{
 | 
			
		||||
	struct nsim_bus_dev *nsim_bus_dev;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL);
 | 
			
		||||
	if (!nsim_bus_dev)
 | 
			
		||||
		return ERR_PTR(-ENOMEM);
 | 
			
		||||
 | 
			
		||||
	nsim_bus_dev->dev.id = nsim_bus_dev_id++;
 | 
			
		||||
	nsim_bus_dev->dev.bus = &nsim_bus;
 | 
			
		||||
	nsim_bus_dev->dev.type = &nsim_bus_dev_type;
 | 
			
		||||
	err = device_register(&nsim_bus_dev->dev);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto err_nsim_bus_dev_free;
 | 
			
		||||
	return nsim_bus_dev;
 | 
			
		||||
 | 
			
		||||
err_nsim_bus_dev_free:
 | 
			
		||||
	kfree(nsim_bus_dev);
 | 
			
		||||
	return ERR_PTR(err);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev)
 | 
			
		||||
{
 | 
			
		||||
	device_unregister(&nsim_bus_dev->dev);
 | 
			
		||||
	kfree(nsim_bus_dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int nsim_bus_init(void)
 | 
			
		||||
{
 | 
			
		||||
	return bus_register(&nsim_bus);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -199,7 +199,7 @@ static int __nsim_dev_init(struct netdevsim *ns)
 | 
			
		|||
	if (err)
 | 
			
		||||
		goto err_fib_destroy;
 | 
			
		||||
 | 
			
		||||
	err = devlink_register(devlink, &ns->dev);
 | 
			
		||||
	err = devlink_register(devlink, &ns->nsim_bus_dev->dev);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto err_resources_unregister;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,120 +25,8 @@
 | 
			
		|||
 | 
			
		||||
#include "netdevsim.h"
 | 
			
		||||
 | 
			
		||||
static u32 nsim_dev_id;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct dentry *nsim_ddir;
 | 
			
		||||
 | 
			
		||||
int nsim_num_vf(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct netdevsim *ns = to_nsim(dev);
 | 
			
		||||
 | 
			
		||||
	return ns->num_vfs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nsim_vfs_enable(struct netdevsim *ns, unsigned int num_vfs)
 | 
			
		||||
{
 | 
			
		||||
	ns->vfconfigs = kcalloc(num_vfs, sizeof(struct nsim_vf_config),
 | 
			
		||||
				GFP_KERNEL);
 | 
			
		||||
	if (!ns->vfconfigs)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	ns->num_vfs = num_vfs;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nsim_vfs_disable(struct netdevsim *ns)
 | 
			
		||||
{
 | 
			
		||||
	kfree(ns->vfconfigs);
 | 
			
		||||
	ns->vfconfigs = NULL;
 | 
			
		||||
	ns->num_vfs = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t
 | 
			
		||||
nsim_numvfs_store(struct device *dev, struct device_attribute *attr,
 | 
			
		||||
		  const char *buf, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	struct netdevsim *ns = to_nsim(dev);
 | 
			
		||||
	unsigned int num_vfs;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = kstrtouint(buf, 0, &num_vfs);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	rtnl_lock();
 | 
			
		||||
	if (ns->num_vfs == num_vfs)
 | 
			
		||||
		goto exit_good;
 | 
			
		||||
	if (ns->num_vfs && num_vfs) {
 | 
			
		||||
		ret = -EBUSY;
 | 
			
		||||
		goto exit_unlock;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (num_vfs) {
 | 
			
		||||
		ret = nsim_vfs_enable(ns, num_vfs);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			goto exit_unlock;
 | 
			
		||||
	} else {
 | 
			
		||||
		nsim_vfs_disable(ns);
 | 
			
		||||
	}
 | 
			
		||||
exit_good:
 | 
			
		||||
	ret = count;
 | 
			
		||||
exit_unlock:
 | 
			
		||||
	rtnl_unlock();
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t
 | 
			
		||||
nsim_numvfs_show(struct device *dev, struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct netdevsim *ns = to_nsim(dev);
 | 
			
		||||
 | 
			
		||||
	return sprintf(buf, "%u\n", ns->num_vfs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct device_attribute nsim_numvfs_attr =
 | 
			
		||||
	__ATTR(sriov_numvfs, 0664, nsim_numvfs_show, nsim_numvfs_store);
 | 
			
		||||
 | 
			
		||||
static struct attribute *nsim_dev_attrs[] = {
 | 
			
		||||
	&nsim_numvfs_attr.attr,
 | 
			
		||||
	NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct attribute_group nsim_dev_attr_group = {
 | 
			
		||||
	.attrs = nsim_dev_attrs,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct attribute_group *nsim_dev_attr_groups[] = {
 | 
			
		||||
	&nsim_dev_attr_group,
 | 
			
		||||
	NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void nsim_dev_release(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct netdevsim *ns = to_nsim(dev);
 | 
			
		||||
 | 
			
		||||
	nsim_vfs_disable(ns);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct device_type nsim_dev_type = {
 | 
			
		||||
	.groups = nsim_dev_attr_groups,
 | 
			
		||||
	.release = nsim_dev_release,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int nsim_get_port_parent_id(struct net_device *dev,
 | 
			
		||||
				   struct netdev_phys_item_id *ppid)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -190,7 +78,7 @@ static void nsim_free(struct net_device *dev)
 | 
			
		|||
	struct netdevsim *ns = netdev_priv(dev);
 | 
			
		||||
 | 
			
		||||
	nsim_dev_exit(ns);
 | 
			
		||||
	device_unregister(&ns->dev);
 | 
			
		||||
	nsim_bus_dev_del(ns->nsim_bus_dev);
 | 
			
		||||
	/* netdev and vf state will be freed out of device_release() */
 | 
			
		||||
	nsim_sdev_put(ns->sdev);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -271,11 +159,12 @@ nsim_setup_tc_block(struct net_device *dev, struct tc_block_offload *f)
 | 
			
		|||
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;
 | 
			
		||||
 | 
			
		||||
	/* Only refuse multicast addresses, zero address can mean unset/any. */
 | 
			
		||||
	if (vf >= ns->num_vfs || is_multicast_ether_addr(mac))
 | 
			
		||||
	if (vf >= nsim_bus_dev->num_vfs || is_multicast_ether_addr(mac))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	memcpy(ns->vfconfigs[vf].vf_mac, mac, ETH_ALEN);
 | 
			
		||||
	memcpy(nsim_bus_dev->vfconfigs[vf].vf_mac, mac, ETH_ALEN);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -284,13 +173,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;
 | 
			
		||||
 | 
			
		||||
	if (vf >= ns->num_vfs || vlan > 4095 || qos > 7)
 | 
			
		||||
	if (vf >= nsim_bus_dev->num_vfs || vlan > 4095 || qos > 7)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	ns->vfconfigs[vf].vlan = vlan;
 | 
			
		||||
	ns->vfconfigs[vf].qos = qos;
 | 
			
		||||
	ns->vfconfigs[vf].vlan_proto = vlan_proto;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].vlan = vlan;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].qos = qos;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].vlan_proto = vlan_proto;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -298,12 +188,13 @@ 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;
 | 
			
		||||
 | 
			
		||||
	if (vf >= ns->num_vfs)
 | 
			
		||||
	if (vf >= nsim_bus_dev->num_vfs)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	ns->vfconfigs[vf].min_tx_rate = min;
 | 
			
		||||
	ns->vfconfigs[vf].max_tx_rate = max;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].min_tx_rate = min;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].max_tx_rate = max;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -311,10 +202,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;
 | 
			
		||||
 | 
			
		||||
	if (vf >= ns->num_vfs)
 | 
			
		||||
	if (vf >= nsim_bus_dev->num_vfs)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	ns->vfconfigs[vf].spoofchk_enabled = val;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].spoofchk_enabled = val;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -322,10 +214,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;
 | 
			
		||||
 | 
			
		||||
	if (vf >= ns->num_vfs)
 | 
			
		||||
	if (vf >= nsim_bus_dev->num_vfs)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	ns->vfconfigs[vf].rss_query_enabled = val;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].rss_query_enabled = val;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -333,10 +226,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;
 | 
			
		||||
 | 
			
		||||
	if (vf >= ns->num_vfs)
 | 
			
		||||
	if (vf >= nsim_bus_dev->num_vfs)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	ns->vfconfigs[vf].trusted = val;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].trusted = val;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -345,21 +239,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;
 | 
			
		||||
 | 
			
		||||
	if (vf >= ns->num_vfs)
 | 
			
		||||
	if (vf >= nsim_bus_dev->num_vfs)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	ivi->vf = vf;
 | 
			
		||||
	ivi->linkstate = ns->vfconfigs[vf].link_state;
 | 
			
		||||
	ivi->min_tx_rate = ns->vfconfigs[vf].min_tx_rate;
 | 
			
		||||
	ivi->max_tx_rate = ns->vfconfigs[vf].max_tx_rate;
 | 
			
		||||
	ivi->vlan = ns->vfconfigs[vf].vlan;
 | 
			
		||||
	ivi->vlan_proto = ns->vfconfigs[vf].vlan_proto;
 | 
			
		||||
	ivi->qos = ns->vfconfigs[vf].qos;
 | 
			
		||||
	memcpy(&ivi->mac, ns->vfconfigs[vf].vf_mac, ETH_ALEN);
 | 
			
		||||
	ivi->spoofchk = ns->vfconfigs[vf].spoofchk_enabled;
 | 
			
		||||
	ivi->trusted = ns->vfconfigs[vf].trusted;
 | 
			
		||||
	ivi->rss_query_en = ns->vfconfigs[vf].rss_query_enabled;
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -367,8 +262,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;
 | 
			
		||||
 | 
			
		||||
	if (vf >= ns->num_vfs)
 | 
			
		||||
	if (vf >= nsim_bus_dev->num_vfs)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	switch (state) {
 | 
			
		||||
| 
						 | 
				
			
			@ -380,7 +276,7 @@ static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state)
 | 
			
		|||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ns->vfconfigs[vf].link_state = state;
 | 
			
		||||
	nsim_bus_dev->vfconfigs[vf].link_state = state;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -490,19 +386,18 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev,
 | 
			
		|||
	if (IS_ERR(ns->sdev))
 | 
			
		||||
		return PTR_ERR(ns->sdev);
 | 
			
		||||
 | 
			
		||||
	ns->dev.id = nsim_dev_id++;
 | 
			
		||||
	ns->dev.bus = &nsim_bus;
 | 
			
		||||
	ns->dev.type = &nsim_dev_type;
 | 
			
		||||
	err = device_register(&ns->dev);
 | 
			
		||||
	if (err)
 | 
			
		||||
	ns->nsim_bus_dev = nsim_bus_dev_new();
 | 
			
		||||
	if (IS_ERR(ns->nsim_bus_dev)) {
 | 
			
		||||
		err = PTR_ERR(ns->nsim_bus_dev);
 | 
			
		||||
		goto err_sdev_put;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SET_NETDEV_DEV(dev, &ns->dev);
 | 
			
		||||
	SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev);
 | 
			
		||||
	ns->netdev = dev;
 | 
			
		||||
 | 
			
		||||
	err = nsim_dev_init(ns);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto err_unreg_dev;
 | 
			
		||||
		goto err_dev_del;
 | 
			
		||||
 | 
			
		||||
	err = register_netdevice(dev);
 | 
			
		||||
	if (err)
 | 
			
		||||
| 
						 | 
				
			
			@ -511,8 +406,8 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev,
 | 
			
		|||
 | 
			
		||||
err_dev_exit:
 | 
			
		||||
	nsim_dev_exit(ns);
 | 
			
		||||
err_unreg_dev:
 | 
			
		||||
	device_unregister(&ns->dev);
 | 
			
		||||
err_dev_del:
 | 
			
		||||
	nsim_bus_dev_del(ns->nsim_bus_dev);
 | 
			
		||||
err_sdev_put:
 | 
			
		||||
	nsim_sdev_put(ns->sdev);
 | 
			
		||||
	return err;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,14 +85,11 @@ struct netdevsim {
 | 
			
		|||
	u64 tx_bytes;
 | 
			
		||||
	struct u64_stats_sync syncp;
 | 
			
		||||
 | 
			
		||||
	struct device dev;
 | 
			
		||||
	struct nsim_bus_dev *nsim_bus_dev;
 | 
			
		||||
	struct netdevsim_shared_dev *sdev;
 | 
			
		||||
 | 
			
		||||
	struct dentry *ddir;
 | 
			
		||||
 | 
			
		||||
	unsigned int num_vfs;
 | 
			
		||||
	struct nsim_vf_config *vfconfigs;
 | 
			
		||||
 | 
			
		||||
	struct bpf_prog	*bpf_offloaded;
 | 
			
		||||
	u32 bpf_offloaded_id;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -184,14 +181,26 @@ static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb)
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline struct netdevsim *to_nsim(struct device *ptr)
 | 
			
		||||
{
 | 
			
		||||
	return container_of(ptr, struct netdevsim, dev);
 | 
			
		||||
}
 | 
			
		||||
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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int nsim_num_vf(struct device *dev);
 | 
			
		||||
 | 
			
		||||
extern struct bus_type nsim_bus;
 | 
			
		||||
struct nsim_bus_dev {
 | 
			
		||||
	struct device dev;
 | 
			
		||||
	unsigned int num_vfs;
 | 
			
		||||
	struct nsim_vf_config *vfconfigs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct nsim_bus_dev *nsim_bus_dev_new(void);
 | 
			
		||||
void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev);
 | 
			
		||||
int nsim_bus_init(void);
 | 
			
		||||
void nsim_bus_exit(void);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue