1925f5afeSJiri Pirko // SPDX-License-Identifier: GPL-2.0 2925f5afeSJiri Pirko /* Copyright (C) 2017 Netronome Systems, Inc. 3925f5afeSJiri Pirko * Copyright (C) 2019 Mellanox Technologies. All rights reserved 4925f5afeSJiri Pirko */ 5925f5afeSJiri Pirko 6925f5afeSJiri Pirko #include <linux/device.h> 7*57ce9774SJiri Pirko #include <linux/idr.h> 840e4fe4cSJiri Pirko #include <linux/kernel.h> 940e4fe4cSJiri Pirko #include <linux/rtnetlink.h> 1040e4fe4cSJiri Pirko #include <linux/slab.h> 1140e4fe4cSJiri Pirko #include <linux/sysfs.h> 12925f5afeSJiri Pirko 13925f5afeSJiri Pirko #include "netdevsim.h" 14925f5afeSJiri Pirko 15*57ce9774SJiri Pirko static DEFINE_IDA(nsim_bus_dev_ids); 1640e4fe4cSJiri Pirko 1740e4fe4cSJiri Pirko static struct nsim_bus_dev *to_nsim_bus_dev(struct device *dev) 1840e4fe4cSJiri Pirko { 1940e4fe4cSJiri Pirko return container_of(dev, struct nsim_bus_dev, dev); 2040e4fe4cSJiri Pirko } 2140e4fe4cSJiri Pirko 2240e4fe4cSJiri Pirko static int nsim_bus_dev_vfs_enable(struct nsim_bus_dev *nsim_bus_dev, 2340e4fe4cSJiri Pirko unsigned int num_vfs) 2440e4fe4cSJiri Pirko { 2540e4fe4cSJiri Pirko nsim_bus_dev->vfconfigs = kcalloc(num_vfs, 2640e4fe4cSJiri Pirko sizeof(struct nsim_vf_config), 2740e4fe4cSJiri Pirko GFP_KERNEL); 2840e4fe4cSJiri Pirko if (!nsim_bus_dev->vfconfigs) 2940e4fe4cSJiri Pirko return -ENOMEM; 3040e4fe4cSJiri Pirko nsim_bus_dev->num_vfs = num_vfs; 3140e4fe4cSJiri Pirko 3240e4fe4cSJiri Pirko return 0; 3340e4fe4cSJiri Pirko } 3440e4fe4cSJiri Pirko 3540e4fe4cSJiri Pirko static void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev) 3640e4fe4cSJiri Pirko { 3740e4fe4cSJiri Pirko kfree(nsim_bus_dev->vfconfigs); 3840e4fe4cSJiri Pirko nsim_bus_dev->vfconfigs = NULL; 3940e4fe4cSJiri Pirko nsim_bus_dev->num_vfs = 0; 4040e4fe4cSJiri Pirko } 4140e4fe4cSJiri Pirko 4240e4fe4cSJiri Pirko static ssize_t 4340e4fe4cSJiri Pirko nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr, 4440e4fe4cSJiri Pirko const char *buf, size_t count) 4540e4fe4cSJiri Pirko { 4640e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 4740e4fe4cSJiri Pirko unsigned int num_vfs; 4840e4fe4cSJiri Pirko int ret; 4940e4fe4cSJiri Pirko 5040e4fe4cSJiri Pirko ret = kstrtouint(buf, 0, &num_vfs); 5140e4fe4cSJiri Pirko if (ret) 5240e4fe4cSJiri Pirko return ret; 5340e4fe4cSJiri Pirko 5440e4fe4cSJiri Pirko rtnl_lock(); 5540e4fe4cSJiri Pirko if (nsim_bus_dev->num_vfs == num_vfs) 5640e4fe4cSJiri Pirko goto exit_good; 5740e4fe4cSJiri Pirko if (nsim_bus_dev->num_vfs && num_vfs) { 5840e4fe4cSJiri Pirko ret = -EBUSY; 5940e4fe4cSJiri Pirko goto exit_unlock; 6040e4fe4cSJiri Pirko } 6140e4fe4cSJiri Pirko 6240e4fe4cSJiri Pirko if (num_vfs) { 6340e4fe4cSJiri Pirko ret = nsim_bus_dev_vfs_enable(nsim_bus_dev, num_vfs); 6440e4fe4cSJiri Pirko if (ret) 6540e4fe4cSJiri Pirko goto exit_unlock; 6640e4fe4cSJiri Pirko } else { 6740e4fe4cSJiri Pirko nsim_bus_dev_vfs_disable(nsim_bus_dev); 6840e4fe4cSJiri Pirko } 6940e4fe4cSJiri Pirko exit_good: 7040e4fe4cSJiri Pirko ret = count; 7140e4fe4cSJiri Pirko exit_unlock: 7240e4fe4cSJiri Pirko rtnl_unlock(); 7340e4fe4cSJiri Pirko 7440e4fe4cSJiri Pirko return ret; 7540e4fe4cSJiri Pirko } 7640e4fe4cSJiri Pirko 7740e4fe4cSJiri Pirko static ssize_t 7840e4fe4cSJiri Pirko nsim_bus_dev_numvfs_show(struct device *dev, 7940e4fe4cSJiri Pirko struct device_attribute *attr, char *buf) 8040e4fe4cSJiri Pirko { 8140e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 8240e4fe4cSJiri Pirko 8340e4fe4cSJiri Pirko return sprintf(buf, "%u\n", nsim_bus_dev->num_vfs); 8440e4fe4cSJiri Pirko } 8540e4fe4cSJiri Pirko 8640e4fe4cSJiri Pirko static struct device_attribute nsim_bus_dev_numvfs_attr = 8740e4fe4cSJiri Pirko __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show, 8840e4fe4cSJiri Pirko nsim_bus_dev_numvfs_store); 8940e4fe4cSJiri Pirko 9040e4fe4cSJiri Pirko static struct attribute *nsim_bus_dev_attrs[] = { 9140e4fe4cSJiri Pirko &nsim_bus_dev_numvfs_attr.attr, 9240e4fe4cSJiri Pirko NULL, 9340e4fe4cSJiri Pirko }; 9440e4fe4cSJiri Pirko 9540e4fe4cSJiri Pirko static const struct attribute_group nsim_bus_dev_attr_group = { 9640e4fe4cSJiri Pirko .attrs = nsim_bus_dev_attrs, 9740e4fe4cSJiri Pirko }; 9840e4fe4cSJiri Pirko 9940e4fe4cSJiri Pirko static const struct attribute_group *nsim_bus_dev_attr_groups[] = { 10040e4fe4cSJiri Pirko &nsim_bus_dev_attr_group, 10140e4fe4cSJiri Pirko NULL, 10240e4fe4cSJiri Pirko }; 10340e4fe4cSJiri Pirko 10440e4fe4cSJiri Pirko static void nsim_bus_dev_release(struct device *dev) 10540e4fe4cSJiri Pirko { 10640e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 10740e4fe4cSJiri Pirko 10840e4fe4cSJiri Pirko nsim_bus_dev_vfs_disable(nsim_bus_dev); 10940e4fe4cSJiri Pirko } 11040e4fe4cSJiri Pirko 11140e4fe4cSJiri Pirko static struct device_type nsim_bus_dev_type = { 11240e4fe4cSJiri Pirko .groups = nsim_bus_dev_attr_groups, 11340e4fe4cSJiri Pirko .release = nsim_bus_dev_release, 11440e4fe4cSJiri Pirko }; 11540e4fe4cSJiri Pirko 11640e4fe4cSJiri Pirko int nsim_num_vf(struct device *dev) 11740e4fe4cSJiri Pirko { 11840e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 11940e4fe4cSJiri Pirko 12040e4fe4cSJiri Pirko return nsim_bus_dev->num_vfs; 12140e4fe4cSJiri Pirko } 12240e4fe4cSJiri Pirko 12340e4fe4cSJiri Pirko static struct bus_type nsim_bus = { 124925f5afeSJiri Pirko .name = DRV_NAME, 125925f5afeSJiri Pirko .dev_name = DRV_NAME, 126925f5afeSJiri Pirko .num_vf = nsim_num_vf, 127925f5afeSJiri Pirko }; 128925f5afeSJiri Pirko 12940e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev_new(void) 13040e4fe4cSJiri Pirko { 13140e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 13240e4fe4cSJiri Pirko int err; 13340e4fe4cSJiri Pirko 13440e4fe4cSJiri Pirko nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL); 13540e4fe4cSJiri Pirko if (!nsim_bus_dev) 13640e4fe4cSJiri Pirko return ERR_PTR(-ENOMEM); 13740e4fe4cSJiri Pirko 138*57ce9774SJiri Pirko err = ida_alloc(&nsim_bus_dev_ids, GFP_KERNEL); 139*57ce9774SJiri Pirko if (err < 0) 140*57ce9774SJiri Pirko goto err_nsim_bus_dev_free; 141*57ce9774SJiri Pirko nsim_bus_dev->dev.id = err; 14240e4fe4cSJiri Pirko nsim_bus_dev->dev.bus = &nsim_bus; 14340e4fe4cSJiri Pirko nsim_bus_dev->dev.type = &nsim_bus_dev_type; 14440e4fe4cSJiri Pirko err = device_register(&nsim_bus_dev->dev); 14540e4fe4cSJiri Pirko if (err) 146*57ce9774SJiri Pirko goto err_nsim_bus_dev_id_free; 14740e4fe4cSJiri Pirko return nsim_bus_dev; 14840e4fe4cSJiri Pirko 149*57ce9774SJiri Pirko err_nsim_bus_dev_id_free: 150*57ce9774SJiri Pirko ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); 15140e4fe4cSJiri Pirko err_nsim_bus_dev_free: 15240e4fe4cSJiri Pirko kfree(nsim_bus_dev); 15340e4fe4cSJiri Pirko return ERR_PTR(err); 15440e4fe4cSJiri Pirko } 15540e4fe4cSJiri Pirko 15640e4fe4cSJiri Pirko void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) 15740e4fe4cSJiri Pirko { 15840e4fe4cSJiri Pirko device_unregister(&nsim_bus_dev->dev); 159*57ce9774SJiri Pirko ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); 16040e4fe4cSJiri Pirko kfree(nsim_bus_dev); 16140e4fe4cSJiri Pirko } 16240e4fe4cSJiri Pirko 16323d415daSJiri Pirko static struct device_driver nsim_driver = { 16423d415daSJiri Pirko .name = DRV_NAME, 16523d415daSJiri Pirko .bus = &nsim_bus, 16623d415daSJiri Pirko .owner = THIS_MODULE, 16723d415daSJiri Pirko }; 16823d415daSJiri Pirko 169925f5afeSJiri Pirko int nsim_bus_init(void) 170925f5afeSJiri Pirko { 17123d415daSJiri Pirko int err; 17223d415daSJiri Pirko 17323d415daSJiri Pirko err = bus_register(&nsim_bus); 17423d415daSJiri Pirko if (err) 17523d415daSJiri Pirko return err; 17623d415daSJiri Pirko err = driver_register(&nsim_driver); 17723d415daSJiri Pirko if (err) 17823d415daSJiri Pirko goto err_bus_unregister; 17923d415daSJiri Pirko return 0; 18023d415daSJiri Pirko 18123d415daSJiri Pirko err_bus_unregister: 18223d415daSJiri Pirko bus_unregister(&nsim_bus); 18323d415daSJiri Pirko return err; 184925f5afeSJiri Pirko } 185925f5afeSJiri Pirko 186925f5afeSJiri Pirko void nsim_bus_exit(void) 187925f5afeSJiri Pirko { 18823d415daSJiri Pirko driver_unregister(&nsim_driver); 189925f5afeSJiri Pirko bus_unregister(&nsim_bus); 190925f5afeSJiri Pirko } 191