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> 757ce9774SJiri Pirko #include <linux/idr.h> 840e4fe4cSJiri Pirko #include <linux/kernel.h> 9f9d9db47SJiri Pirko #include <linux/list.h> 10f9d9db47SJiri Pirko #include <linux/mutex.h> 1140e4fe4cSJiri Pirko #include <linux/rtnetlink.h> 1240e4fe4cSJiri Pirko #include <linux/slab.h> 1340e4fe4cSJiri Pirko #include <linux/sysfs.h> 14925f5afeSJiri Pirko 15925f5afeSJiri Pirko #include "netdevsim.h" 16925f5afeSJiri Pirko 1757ce9774SJiri Pirko static DEFINE_IDA(nsim_bus_dev_ids); 18f9d9db47SJiri Pirko static LIST_HEAD(nsim_bus_dev_list); 19f9d9db47SJiri Pirko static DEFINE_MUTEX(nsim_bus_dev_list_lock); 2040e4fe4cSJiri Pirko 2140e4fe4cSJiri Pirko static struct nsim_bus_dev *to_nsim_bus_dev(struct device *dev) 2240e4fe4cSJiri Pirko { 2340e4fe4cSJiri Pirko return container_of(dev, struct nsim_bus_dev, dev); 2440e4fe4cSJiri Pirko } 2540e4fe4cSJiri Pirko 2640e4fe4cSJiri Pirko static int nsim_bus_dev_vfs_enable(struct nsim_bus_dev *nsim_bus_dev, 2740e4fe4cSJiri Pirko unsigned int num_vfs) 2840e4fe4cSJiri Pirko { 2940e4fe4cSJiri Pirko nsim_bus_dev->vfconfigs = kcalloc(num_vfs, 3040e4fe4cSJiri Pirko sizeof(struct nsim_vf_config), 3140e4fe4cSJiri Pirko GFP_KERNEL); 3240e4fe4cSJiri Pirko if (!nsim_bus_dev->vfconfigs) 3340e4fe4cSJiri Pirko return -ENOMEM; 3440e4fe4cSJiri Pirko nsim_bus_dev->num_vfs = num_vfs; 3540e4fe4cSJiri Pirko 3640e4fe4cSJiri Pirko return 0; 3740e4fe4cSJiri Pirko } 3840e4fe4cSJiri Pirko 3940e4fe4cSJiri Pirko static void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev) 4040e4fe4cSJiri Pirko { 4140e4fe4cSJiri Pirko kfree(nsim_bus_dev->vfconfigs); 4240e4fe4cSJiri Pirko nsim_bus_dev->vfconfigs = NULL; 4340e4fe4cSJiri Pirko nsim_bus_dev->num_vfs = 0; 4440e4fe4cSJiri Pirko } 4540e4fe4cSJiri Pirko 4640e4fe4cSJiri Pirko static ssize_t 4740e4fe4cSJiri Pirko nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr, 4840e4fe4cSJiri Pirko const char *buf, size_t count) 4940e4fe4cSJiri Pirko { 5040e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 5140e4fe4cSJiri Pirko unsigned int num_vfs; 5240e4fe4cSJiri Pirko int ret; 5340e4fe4cSJiri Pirko 5440e4fe4cSJiri Pirko ret = kstrtouint(buf, 0, &num_vfs); 5540e4fe4cSJiri Pirko if (ret) 5640e4fe4cSJiri Pirko return ret; 5740e4fe4cSJiri Pirko 5840e4fe4cSJiri Pirko rtnl_lock(); 5940e4fe4cSJiri Pirko if (nsim_bus_dev->num_vfs == num_vfs) 6040e4fe4cSJiri Pirko goto exit_good; 6140e4fe4cSJiri Pirko if (nsim_bus_dev->num_vfs && num_vfs) { 6240e4fe4cSJiri Pirko ret = -EBUSY; 6340e4fe4cSJiri Pirko goto exit_unlock; 6440e4fe4cSJiri Pirko } 6540e4fe4cSJiri Pirko 6640e4fe4cSJiri Pirko if (num_vfs) { 6740e4fe4cSJiri Pirko ret = nsim_bus_dev_vfs_enable(nsim_bus_dev, num_vfs); 6840e4fe4cSJiri Pirko if (ret) 6940e4fe4cSJiri Pirko goto exit_unlock; 7040e4fe4cSJiri Pirko } else { 7140e4fe4cSJiri Pirko nsim_bus_dev_vfs_disable(nsim_bus_dev); 7240e4fe4cSJiri Pirko } 7340e4fe4cSJiri Pirko exit_good: 7440e4fe4cSJiri Pirko ret = count; 7540e4fe4cSJiri Pirko exit_unlock: 7640e4fe4cSJiri Pirko rtnl_unlock(); 7740e4fe4cSJiri Pirko 7840e4fe4cSJiri Pirko return ret; 7940e4fe4cSJiri Pirko } 8040e4fe4cSJiri Pirko 8140e4fe4cSJiri Pirko static ssize_t 8240e4fe4cSJiri Pirko nsim_bus_dev_numvfs_show(struct device *dev, 8340e4fe4cSJiri Pirko struct device_attribute *attr, char *buf) 8440e4fe4cSJiri Pirko { 8540e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 8640e4fe4cSJiri Pirko 8740e4fe4cSJiri Pirko return sprintf(buf, "%u\n", nsim_bus_dev->num_vfs); 8840e4fe4cSJiri Pirko } 8940e4fe4cSJiri Pirko 9040e4fe4cSJiri Pirko static struct device_attribute nsim_bus_dev_numvfs_attr = 9140e4fe4cSJiri Pirko __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show, 9240e4fe4cSJiri Pirko nsim_bus_dev_numvfs_store); 9340e4fe4cSJiri Pirko 9440e4fe4cSJiri Pirko static struct attribute *nsim_bus_dev_attrs[] = { 9540e4fe4cSJiri Pirko &nsim_bus_dev_numvfs_attr.attr, 9640e4fe4cSJiri Pirko NULL, 9740e4fe4cSJiri Pirko }; 9840e4fe4cSJiri Pirko 9940e4fe4cSJiri Pirko static const struct attribute_group nsim_bus_dev_attr_group = { 10040e4fe4cSJiri Pirko .attrs = nsim_bus_dev_attrs, 10140e4fe4cSJiri Pirko }; 10240e4fe4cSJiri Pirko 10340e4fe4cSJiri Pirko static const struct attribute_group *nsim_bus_dev_attr_groups[] = { 10440e4fe4cSJiri Pirko &nsim_bus_dev_attr_group, 10540e4fe4cSJiri Pirko NULL, 10640e4fe4cSJiri Pirko }; 10740e4fe4cSJiri Pirko 10840e4fe4cSJiri Pirko static void nsim_bus_dev_release(struct device *dev) 10940e4fe4cSJiri Pirko { 11040e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 11140e4fe4cSJiri Pirko 11240e4fe4cSJiri Pirko nsim_bus_dev_vfs_disable(nsim_bus_dev); 11340e4fe4cSJiri Pirko } 11440e4fe4cSJiri Pirko 11540e4fe4cSJiri Pirko static struct device_type nsim_bus_dev_type = { 11640e4fe4cSJiri Pirko .groups = nsim_bus_dev_attr_groups, 11740e4fe4cSJiri Pirko .release = nsim_bus_dev_release, 11840e4fe4cSJiri Pirko }; 11940e4fe4cSJiri Pirko 120f9d9db47SJiri Pirko static ssize_t 121f9d9db47SJiri Pirko new_device_store(struct bus_type *bus, const char *buf, size_t count) 122f9d9db47SJiri Pirko { 123f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 124f9d9db47SJiri Pirko unsigned int port_count; 125f9d9db47SJiri Pirko unsigned int id; 126f9d9db47SJiri Pirko int err; 127f9d9db47SJiri Pirko 128f9d9db47SJiri Pirko err = sscanf(buf, "%u %u", &id, &port_count); 129f9d9db47SJiri Pirko switch (err) { 130f9d9db47SJiri Pirko case 1: 131f9d9db47SJiri Pirko port_count = 1; 132f9d9db47SJiri Pirko /* pass through */ 133f9d9db47SJiri Pirko case 2: 134f9d9db47SJiri Pirko if (id > INT_MAX) { 135f9d9db47SJiri Pirko pr_err("Value of \"id\" is too big.\n"); 136f9d9db47SJiri Pirko return -EINVAL; 137f9d9db47SJiri Pirko } 138f9d9db47SJiri Pirko break; 139f9d9db47SJiri Pirko default: 140f9d9db47SJiri Pirko pr_err("Format for adding new device is \"id port_count\" (uint uint).\n"); 141f9d9db47SJiri Pirko return -EINVAL; 142f9d9db47SJiri Pirko } 143f9d9db47SJiri Pirko nsim_bus_dev = nsim_bus_dev_new(id, port_count); 144f9d9db47SJiri Pirko if (IS_ERR(nsim_bus_dev)) 145f9d9db47SJiri Pirko return PTR_ERR(nsim_bus_dev); 146f9d9db47SJiri Pirko 147f9d9db47SJiri Pirko mutex_lock(&nsim_bus_dev_list_lock); 148f9d9db47SJiri Pirko list_add_tail(&nsim_bus_dev->list, &nsim_bus_dev_list); 149f9d9db47SJiri Pirko mutex_unlock(&nsim_bus_dev_list_lock); 150f9d9db47SJiri Pirko 151f9d9db47SJiri Pirko return count; 152f9d9db47SJiri Pirko } 153f9d9db47SJiri Pirko static BUS_ATTR_WO(new_device); 154f9d9db47SJiri Pirko 155f9d9db47SJiri Pirko static ssize_t 156f9d9db47SJiri Pirko del_device_store(struct bus_type *bus, const char *buf, size_t count) 157f9d9db47SJiri Pirko { 158f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev, *tmp; 159f9d9db47SJiri Pirko unsigned int id; 160f9d9db47SJiri Pirko int err; 161f9d9db47SJiri Pirko 162f9d9db47SJiri Pirko err = sscanf(buf, "%u", &id); 163f9d9db47SJiri Pirko switch (err) { 164f9d9db47SJiri Pirko case 1: 165f9d9db47SJiri Pirko if (id > INT_MAX) { 166f9d9db47SJiri Pirko pr_err("Value of \"id\" is too big.\n"); 167f9d9db47SJiri Pirko return -EINVAL; 168f9d9db47SJiri Pirko } 169f9d9db47SJiri Pirko break; 170f9d9db47SJiri Pirko default: 171f9d9db47SJiri Pirko pr_err("Format for deleting device is \"id\" (uint).\n"); 172f9d9db47SJiri Pirko return -EINVAL; 173f9d9db47SJiri Pirko } 174f9d9db47SJiri Pirko 175f9d9db47SJiri Pirko err = -ENOENT; 176f9d9db47SJiri Pirko mutex_lock(&nsim_bus_dev_list_lock); 177f9d9db47SJiri Pirko list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) { 178f9d9db47SJiri Pirko if (nsim_bus_dev->dev.id != id) 179f9d9db47SJiri Pirko continue; 180f9d9db47SJiri Pirko list_del(&nsim_bus_dev->list); 181f9d9db47SJiri Pirko nsim_bus_dev_del(nsim_bus_dev); 182f9d9db47SJiri Pirko err = 0; 183f9d9db47SJiri Pirko break; 184f9d9db47SJiri Pirko } 185f9d9db47SJiri Pirko mutex_unlock(&nsim_bus_dev_list_lock); 186f9d9db47SJiri Pirko return !err ? count : err; 187f9d9db47SJiri Pirko } 188f9d9db47SJiri Pirko static BUS_ATTR_WO(del_device); 189f9d9db47SJiri Pirko 190f9d9db47SJiri Pirko static struct attribute *nsim_bus_attrs[] = { 191f9d9db47SJiri Pirko &bus_attr_new_device.attr, 192f9d9db47SJiri Pirko &bus_attr_del_device.attr, 193f9d9db47SJiri Pirko NULL 194f9d9db47SJiri Pirko }; 195f9d9db47SJiri Pirko ATTRIBUTE_GROUPS(nsim_bus); 196f9d9db47SJiri Pirko 197*8320d145SJiri Pirko static int nsim_bus_probe(struct device *dev) 198*8320d145SJiri Pirko { 199*8320d145SJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 200*8320d145SJiri Pirko 201*8320d145SJiri Pirko return nsim_dev_probe(nsim_bus_dev); 202*8320d145SJiri Pirko } 203*8320d145SJiri Pirko 204*8320d145SJiri Pirko static int nsim_bus_remove(struct device *dev) 205*8320d145SJiri Pirko { 206*8320d145SJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 207*8320d145SJiri Pirko 208*8320d145SJiri Pirko nsim_dev_remove(nsim_bus_dev); 209*8320d145SJiri Pirko return 0; 210*8320d145SJiri Pirko } 211*8320d145SJiri Pirko 21240e4fe4cSJiri Pirko int nsim_num_vf(struct device *dev) 21340e4fe4cSJiri Pirko { 21440e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 21540e4fe4cSJiri Pirko 21640e4fe4cSJiri Pirko return nsim_bus_dev->num_vfs; 21740e4fe4cSJiri Pirko } 21840e4fe4cSJiri Pirko 21940e4fe4cSJiri Pirko static struct bus_type nsim_bus = { 220925f5afeSJiri Pirko .name = DRV_NAME, 221925f5afeSJiri Pirko .dev_name = DRV_NAME, 222f9d9db47SJiri Pirko .bus_groups = nsim_bus_groups, 223*8320d145SJiri Pirko .probe = nsim_bus_probe, 224*8320d145SJiri Pirko .remove = nsim_bus_remove, 225925f5afeSJiri Pirko .num_vf = nsim_num_vf, 226925f5afeSJiri Pirko }; 227925f5afeSJiri Pirko 228f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count) 22940e4fe4cSJiri Pirko { 23040e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 23140e4fe4cSJiri Pirko int err; 23240e4fe4cSJiri Pirko 23340e4fe4cSJiri Pirko nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL); 23440e4fe4cSJiri Pirko if (!nsim_bus_dev) 23540e4fe4cSJiri Pirko return ERR_PTR(-ENOMEM); 23640e4fe4cSJiri Pirko 237f9d9db47SJiri Pirko err = ida_alloc_range(&nsim_bus_dev_ids, 238f9d9db47SJiri Pirko id == ~0 ? 0 : id, id, GFP_KERNEL); 23957ce9774SJiri Pirko if (err < 0) 24057ce9774SJiri Pirko goto err_nsim_bus_dev_free; 24157ce9774SJiri Pirko nsim_bus_dev->dev.id = err; 24240e4fe4cSJiri Pirko nsim_bus_dev->dev.bus = &nsim_bus; 24340e4fe4cSJiri Pirko nsim_bus_dev->dev.type = &nsim_bus_dev_type; 244f9d9db47SJiri Pirko nsim_bus_dev->port_count = port_count; 245f9d9db47SJiri Pirko 24640e4fe4cSJiri Pirko err = device_register(&nsim_bus_dev->dev); 24740e4fe4cSJiri Pirko if (err) 24857ce9774SJiri Pirko goto err_nsim_bus_dev_id_free; 24940e4fe4cSJiri Pirko return nsim_bus_dev; 25040e4fe4cSJiri Pirko 25157ce9774SJiri Pirko err_nsim_bus_dev_id_free: 25257ce9774SJiri Pirko ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); 25340e4fe4cSJiri Pirko err_nsim_bus_dev_free: 25440e4fe4cSJiri Pirko kfree(nsim_bus_dev); 25540e4fe4cSJiri Pirko return ERR_PTR(err); 25640e4fe4cSJiri Pirko } 25740e4fe4cSJiri Pirko 258*8320d145SJiri Pirko struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns) 259*8320d145SJiri Pirko { 260*8320d145SJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 261*8320d145SJiri Pirko 262*8320d145SJiri Pirko dev_hold(ns->netdev); 263*8320d145SJiri Pirko rtnl_unlock(); 264*8320d145SJiri Pirko nsim_bus_dev = nsim_bus_dev_new(~0, 0); 265*8320d145SJiri Pirko rtnl_lock(); 266*8320d145SJiri Pirko dev_put(ns->netdev); 267*8320d145SJiri Pirko return nsim_bus_dev; 268*8320d145SJiri Pirko } 269*8320d145SJiri Pirko 27040e4fe4cSJiri Pirko void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) 27140e4fe4cSJiri Pirko { 27240e4fe4cSJiri Pirko device_unregister(&nsim_bus_dev->dev); 27357ce9774SJiri Pirko ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); 27440e4fe4cSJiri Pirko kfree(nsim_bus_dev); 27540e4fe4cSJiri Pirko } 27640e4fe4cSJiri Pirko 27723d415daSJiri Pirko static struct device_driver nsim_driver = { 27823d415daSJiri Pirko .name = DRV_NAME, 27923d415daSJiri Pirko .bus = &nsim_bus, 28023d415daSJiri Pirko .owner = THIS_MODULE, 28123d415daSJiri Pirko }; 28223d415daSJiri Pirko 283925f5afeSJiri Pirko int nsim_bus_init(void) 284925f5afeSJiri Pirko { 28523d415daSJiri Pirko int err; 28623d415daSJiri Pirko 28723d415daSJiri Pirko err = bus_register(&nsim_bus); 28823d415daSJiri Pirko if (err) 28923d415daSJiri Pirko return err; 29023d415daSJiri Pirko err = driver_register(&nsim_driver); 29123d415daSJiri Pirko if (err) 29223d415daSJiri Pirko goto err_bus_unregister; 29323d415daSJiri Pirko return 0; 29423d415daSJiri Pirko 29523d415daSJiri Pirko err_bus_unregister: 29623d415daSJiri Pirko bus_unregister(&nsim_bus); 29723d415daSJiri Pirko return err; 298925f5afeSJiri Pirko } 299925f5afeSJiri Pirko 300925f5afeSJiri Pirko void nsim_bus_exit(void) 301925f5afeSJiri Pirko { 302f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev, *tmp; 303f9d9db47SJiri Pirko 304f9d9db47SJiri Pirko mutex_lock(&nsim_bus_dev_list_lock); 305f9d9db47SJiri Pirko list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) { 306f9d9db47SJiri Pirko list_del(&nsim_bus_dev->list); 307f9d9db47SJiri Pirko nsim_bus_dev_del(nsim_bus_dev); 308f9d9db47SJiri Pirko } 309f9d9db47SJiri Pirko mutex_unlock(&nsim_bus_dev_list_lock); 31023d415daSJiri Pirko driver_unregister(&nsim_driver); 311925f5afeSJiri Pirko bus_unregister(&nsim_bus); 312925f5afeSJiri Pirko } 313