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 94*794b2c05SJiri Pirko static ssize_t 95*794b2c05SJiri Pirko new_port_store(struct device *dev, struct device_attribute *attr, 96*794b2c05SJiri Pirko const char *buf, size_t count) 97*794b2c05SJiri Pirko { 98*794b2c05SJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 99*794b2c05SJiri Pirko unsigned int port_index; 100*794b2c05SJiri Pirko int ret; 101*794b2c05SJiri Pirko 102*794b2c05SJiri Pirko ret = kstrtouint(buf, 0, &port_index); 103*794b2c05SJiri Pirko if (ret) 104*794b2c05SJiri Pirko return ret; 105*794b2c05SJiri Pirko ret = nsim_dev_port_add(nsim_bus_dev, port_index); 106*794b2c05SJiri Pirko return ret ? ret : count; 107*794b2c05SJiri Pirko } 108*794b2c05SJiri Pirko 109*794b2c05SJiri Pirko static struct device_attribute nsim_bus_dev_new_port_attr = __ATTR_WO(new_port); 110*794b2c05SJiri Pirko 111*794b2c05SJiri Pirko static ssize_t 112*794b2c05SJiri Pirko del_port_store(struct device *dev, struct device_attribute *attr, 113*794b2c05SJiri Pirko const char *buf, size_t count) 114*794b2c05SJiri Pirko { 115*794b2c05SJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 116*794b2c05SJiri Pirko unsigned int port_index; 117*794b2c05SJiri Pirko int ret; 118*794b2c05SJiri Pirko 119*794b2c05SJiri Pirko ret = kstrtouint(buf, 0, &port_index); 120*794b2c05SJiri Pirko if (ret) 121*794b2c05SJiri Pirko return ret; 122*794b2c05SJiri Pirko ret = nsim_dev_port_del(nsim_bus_dev, port_index); 123*794b2c05SJiri Pirko return ret ? ret : count; 124*794b2c05SJiri Pirko } 125*794b2c05SJiri Pirko 126*794b2c05SJiri Pirko static struct device_attribute nsim_bus_dev_del_port_attr = __ATTR_WO(del_port); 127*794b2c05SJiri Pirko 12840e4fe4cSJiri Pirko static struct attribute *nsim_bus_dev_attrs[] = { 12940e4fe4cSJiri Pirko &nsim_bus_dev_numvfs_attr.attr, 130*794b2c05SJiri Pirko &nsim_bus_dev_new_port_attr.attr, 131*794b2c05SJiri Pirko &nsim_bus_dev_del_port_attr.attr, 13240e4fe4cSJiri Pirko NULL, 13340e4fe4cSJiri Pirko }; 13440e4fe4cSJiri Pirko 13540e4fe4cSJiri Pirko static const struct attribute_group nsim_bus_dev_attr_group = { 13640e4fe4cSJiri Pirko .attrs = nsim_bus_dev_attrs, 13740e4fe4cSJiri Pirko }; 13840e4fe4cSJiri Pirko 13940e4fe4cSJiri Pirko static const struct attribute_group *nsim_bus_dev_attr_groups[] = { 14040e4fe4cSJiri Pirko &nsim_bus_dev_attr_group, 14140e4fe4cSJiri Pirko NULL, 14240e4fe4cSJiri Pirko }; 14340e4fe4cSJiri Pirko 14440e4fe4cSJiri Pirko static void nsim_bus_dev_release(struct device *dev) 14540e4fe4cSJiri Pirko { 14640e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 14740e4fe4cSJiri Pirko 14840e4fe4cSJiri Pirko nsim_bus_dev_vfs_disable(nsim_bus_dev); 14940e4fe4cSJiri Pirko } 15040e4fe4cSJiri Pirko 15140e4fe4cSJiri Pirko static struct device_type nsim_bus_dev_type = { 15240e4fe4cSJiri Pirko .groups = nsim_bus_dev_attr_groups, 15340e4fe4cSJiri Pirko .release = nsim_bus_dev_release, 15440e4fe4cSJiri Pirko }; 15540e4fe4cSJiri Pirko 156f9d9db47SJiri Pirko static ssize_t 157f9d9db47SJiri Pirko new_device_store(struct bus_type *bus, const char *buf, size_t count) 158f9d9db47SJiri Pirko { 159f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 160f9d9db47SJiri Pirko unsigned int port_count; 161f9d9db47SJiri Pirko unsigned int id; 162f9d9db47SJiri Pirko int err; 163f9d9db47SJiri Pirko 164f9d9db47SJiri Pirko err = sscanf(buf, "%u %u", &id, &port_count); 165f9d9db47SJiri Pirko switch (err) { 166f9d9db47SJiri Pirko case 1: 167f9d9db47SJiri Pirko port_count = 1; 168f9d9db47SJiri Pirko /* pass through */ 169f9d9db47SJiri Pirko case 2: 170f9d9db47SJiri Pirko if (id > INT_MAX) { 171f9d9db47SJiri Pirko pr_err("Value of \"id\" is too big.\n"); 172f9d9db47SJiri Pirko return -EINVAL; 173f9d9db47SJiri Pirko } 174f9d9db47SJiri Pirko break; 175f9d9db47SJiri Pirko default: 176f9d9db47SJiri Pirko pr_err("Format for adding new device is \"id port_count\" (uint uint).\n"); 177f9d9db47SJiri Pirko return -EINVAL; 178f9d9db47SJiri Pirko } 179f9d9db47SJiri Pirko nsim_bus_dev = nsim_bus_dev_new(id, port_count); 180f9d9db47SJiri Pirko if (IS_ERR(nsim_bus_dev)) 181f9d9db47SJiri Pirko return PTR_ERR(nsim_bus_dev); 182f9d9db47SJiri Pirko 183f9d9db47SJiri Pirko mutex_lock(&nsim_bus_dev_list_lock); 184f9d9db47SJiri Pirko list_add_tail(&nsim_bus_dev->list, &nsim_bus_dev_list); 185f9d9db47SJiri Pirko mutex_unlock(&nsim_bus_dev_list_lock); 186f9d9db47SJiri Pirko 187f9d9db47SJiri Pirko return count; 188f9d9db47SJiri Pirko } 189f9d9db47SJiri Pirko static BUS_ATTR_WO(new_device); 190f9d9db47SJiri Pirko 191f9d9db47SJiri Pirko static ssize_t 192f9d9db47SJiri Pirko del_device_store(struct bus_type *bus, const char *buf, size_t count) 193f9d9db47SJiri Pirko { 194f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev, *tmp; 195f9d9db47SJiri Pirko unsigned int id; 196f9d9db47SJiri Pirko int err; 197f9d9db47SJiri Pirko 198f9d9db47SJiri Pirko err = sscanf(buf, "%u", &id); 199f9d9db47SJiri Pirko switch (err) { 200f9d9db47SJiri Pirko case 1: 201f9d9db47SJiri Pirko if (id > INT_MAX) { 202f9d9db47SJiri Pirko pr_err("Value of \"id\" is too big.\n"); 203f9d9db47SJiri Pirko return -EINVAL; 204f9d9db47SJiri Pirko } 205f9d9db47SJiri Pirko break; 206f9d9db47SJiri Pirko default: 207f9d9db47SJiri Pirko pr_err("Format for deleting device is \"id\" (uint).\n"); 208f9d9db47SJiri Pirko return -EINVAL; 209f9d9db47SJiri Pirko } 210f9d9db47SJiri Pirko 211f9d9db47SJiri Pirko err = -ENOENT; 212f9d9db47SJiri Pirko mutex_lock(&nsim_bus_dev_list_lock); 213f9d9db47SJiri Pirko list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) { 214f9d9db47SJiri Pirko if (nsim_bus_dev->dev.id != id) 215f9d9db47SJiri Pirko continue; 216f9d9db47SJiri Pirko list_del(&nsim_bus_dev->list); 217f9d9db47SJiri Pirko nsim_bus_dev_del(nsim_bus_dev); 218f9d9db47SJiri Pirko err = 0; 219f9d9db47SJiri Pirko break; 220f9d9db47SJiri Pirko } 221f9d9db47SJiri Pirko mutex_unlock(&nsim_bus_dev_list_lock); 222f9d9db47SJiri Pirko return !err ? count : err; 223f9d9db47SJiri Pirko } 224f9d9db47SJiri Pirko static BUS_ATTR_WO(del_device); 225f9d9db47SJiri Pirko 226f9d9db47SJiri Pirko static struct attribute *nsim_bus_attrs[] = { 227f9d9db47SJiri Pirko &bus_attr_new_device.attr, 228f9d9db47SJiri Pirko &bus_attr_del_device.attr, 229f9d9db47SJiri Pirko NULL 230f9d9db47SJiri Pirko }; 231f9d9db47SJiri Pirko ATTRIBUTE_GROUPS(nsim_bus); 232f9d9db47SJiri Pirko 2338320d145SJiri Pirko static int nsim_bus_probe(struct device *dev) 2348320d145SJiri Pirko { 2358320d145SJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 2368320d145SJiri Pirko 2378320d145SJiri Pirko return nsim_dev_probe(nsim_bus_dev); 2388320d145SJiri Pirko } 2398320d145SJiri Pirko 2408320d145SJiri Pirko static int nsim_bus_remove(struct device *dev) 2418320d145SJiri Pirko { 2428320d145SJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 2438320d145SJiri Pirko 2448320d145SJiri Pirko nsim_dev_remove(nsim_bus_dev); 2458320d145SJiri Pirko return 0; 2468320d145SJiri Pirko } 2478320d145SJiri Pirko 24840e4fe4cSJiri Pirko int nsim_num_vf(struct device *dev) 24940e4fe4cSJiri Pirko { 25040e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); 25140e4fe4cSJiri Pirko 25240e4fe4cSJiri Pirko return nsim_bus_dev->num_vfs; 25340e4fe4cSJiri Pirko } 25440e4fe4cSJiri Pirko 25540e4fe4cSJiri Pirko static struct bus_type nsim_bus = { 256925f5afeSJiri Pirko .name = DRV_NAME, 257925f5afeSJiri Pirko .dev_name = DRV_NAME, 258f9d9db47SJiri Pirko .bus_groups = nsim_bus_groups, 2598320d145SJiri Pirko .probe = nsim_bus_probe, 2608320d145SJiri Pirko .remove = nsim_bus_remove, 261925f5afeSJiri Pirko .num_vf = nsim_num_vf, 262925f5afeSJiri Pirko }; 263925f5afeSJiri Pirko 264f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count) 26540e4fe4cSJiri Pirko { 26640e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 26740e4fe4cSJiri Pirko int err; 26840e4fe4cSJiri Pirko 26940e4fe4cSJiri Pirko nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL); 27040e4fe4cSJiri Pirko if (!nsim_bus_dev) 27140e4fe4cSJiri Pirko return ERR_PTR(-ENOMEM); 27240e4fe4cSJiri Pirko 273f9d9db47SJiri Pirko err = ida_alloc_range(&nsim_bus_dev_ids, 274f9d9db47SJiri Pirko id == ~0 ? 0 : id, id, GFP_KERNEL); 27557ce9774SJiri Pirko if (err < 0) 27657ce9774SJiri Pirko goto err_nsim_bus_dev_free; 27757ce9774SJiri Pirko nsim_bus_dev->dev.id = err; 27840e4fe4cSJiri Pirko nsim_bus_dev->dev.bus = &nsim_bus; 27940e4fe4cSJiri Pirko nsim_bus_dev->dev.type = &nsim_bus_dev_type; 280f9d9db47SJiri Pirko nsim_bus_dev->port_count = port_count; 281f9d9db47SJiri Pirko 28240e4fe4cSJiri Pirko err = device_register(&nsim_bus_dev->dev); 28340e4fe4cSJiri Pirko if (err) 28457ce9774SJiri Pirko goto err_nsim_bus_dev_id_free; 28540e4fe4cSJiri Pirko return nsim_bus_dev; 28640e4fe4cSJiri Pirko 28757ce9774SJiri Pirko err_nsim_bus_dev_id_free: 28857ce9774SJiri Pirko ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); 28940e4fe4cSJiri Pirko err_nsim_bus_dev_free: 29040e4fe4cSJiri Pirko kfree(nsim_bus_dev); 29140e4fe4cSJiri Pirko return ERR_PTR(err); 29240e4fe4cSJiri Pirko } 29340e4fe4cSJiri Pirko 2948320d145SJiri Pirko struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns) 2958320d145SJiri Pirko { 2968320d145SJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 2978320d145SJiri Pirko 2988320d145SJiri Pirko dev_hold(ns->netdev); 2998320d145SJiri Pirko rtnl_unlock(); 3008320d145SJiri Pirko nsim_bus_dev = nsim_bus_dev_new(~0, 0); 3018320d145SJiri Pirko rtnl_lock(); 3028320d145SJiri Pirko dev_put(ns->netdev); 3038320d145SJiri Pirko return nsim_bus_dev; 3048320d145SJiri Pirko } 3058320d145SJiri Pirko 30640e4fe4cSJiri Pirko void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) 30740e4fe4cSJiri Pirko { 30840e4fe4cSJiri Pirko device_unregister(&nsim_bus_dev->dev); 30957ce9774SJiri Pirko ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); 31040e4fe4cSJiri Pirko kfree(nsim_bus_dev); 31140e4fe4cSJiri Pirko } 31240e4fe4cSJiri Pirko 31323d415daSJiri Pirko static struct device_driver nsim_driver = { 31423d415daSJiri Pirko .name = DRV_NAME, 31523d415daSJiri Pirko .bus = &nsim_bus, 31623d415daSJiri Pirko .owner = THIS_MODULE, 31723d415daSJiri Pirko }; 31823d415daSJiri Pirko 319925f5afeSJiri Pirko int nsim_bus_init(void) 320925f5afeSJiri Pirko { 32123d415daSJiri Pirko int err; 32223d415daSJiri Pirko 32323d415daSJiri Pirko err = bus_register(&nsim_bus); 32423d415daSJiri Pirko if (err) 32523d415daSJiri Pirko return err; 32623d415daSJiri Pirko err = driver_register(&nsim_driver); 32723d415daSJiri Pirko if (err) 32823d415daSJiri Pirko goto err_bus_unregister; 32923d415daSJiri Pirko return 0; 33023d415daSJiri Pirko 33123d415daSJiri Pirko err_bus_unregister: 33223d415daSJiri Pirko bus_unregister(&nsim_bus); 33323d415daSJiri Pirko return err; 334925f5afeSJiri Pirko } 335925f5afeSJiri Pirko 336925f5afeSJiri Pirko void nsim_bus_exit(void) 337925f5afeSJiri Pirko { 338f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev, *tmp; 339f9d9db47SJiri Pirko 340f9d9db47SJiri Pirko mutex_lock(&nsim_bus_dev_list_lock); 341f9d9db47SJiri Pirko list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) { 342f9d9db47SJiri Pirko list_del(&nsim_bus_dev->list); 343f9d9db47SJiri Pirko nsim_bus_dev_del(nsim_bus_dev); 344f9d9db47SJiri Pirko } 345f9d9db47SJiri Pirko mutex_unlock(&nsim_bus_dev_list_lock); 34623d415daSJiri Pirko driver_unregister(&nsim_driver); 347925f5afeSJiri Pirko bus_unregister(&nsim_bus); 348925f5afeSJiri Pirko } 349