^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Copyright (C) 2017 Netronome Systems, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2019 Mellanox Technologies. All rights reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "netdevsim.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static DEFINE_IDA(nsim_bus_dev_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static LIST_HEAD(nsim_bus_dev_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static DEFINE_MUTEX(nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static bool nsim_bus_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static struct nsim_bus_dev *to_nsim_bus_dev(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return container_of(dev, struct nsim_bus_dev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int nsim_bus_dev_vfs_enable(struct nsim_bus_dev *nsim_bus_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned int num_vfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) nsim_bus_dev->vfconfigs = kcalloc(num_vfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) sizeof(struct nsim_vf_config),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) GFP_KERNEL | __GFP_NOWARN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (!nsim_bus_dev->vfconfigs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) nsim_bus_dev->num_vfs = num_vfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) kfree(nsim_bus_dev->vfconfigs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) nsim_bus_dev->vfconfigs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) nsim_bus_dev->num_vfs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned int num_vfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ret = kstrtouint(buf, 0, &num_vfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (nsim_bus_dev->num_vfs == num_vfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) goto exit_good;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (nsim_bus_dev->num_vfs && num_vfs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) goto exit_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (num_vfs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ret = nsim_bus_dev_vfs_enable(nsim_bus_dev, num_vfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) goto exit_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) nsim_bus_dev_vfs_disable(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) exit_good:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) exit_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) nsim_bus_dev_numvfs_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return sprintf(buf, "%u\n", nsim_bus_dev->num_vfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static struct device_attribute nsim_bus_dev_numvfs_attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) nsim_bus_dev_numvfs_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) new_port_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct nsim_dev *nsim_dev = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct devlink *devlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned int port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* Prevent to use nsim_bus_dev before initialization. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (!smp_load_acquire(&nsim_bus_dev->init))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ret = kstrtouint(buf, 0, &port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) devlink = priv_to_devlink(nsim_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mutex_lock(&nsim_bus_dev->nsim_bus_reload_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) devlink_reload_disable(devlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ret = nsim_dev_port_add(nsim_bus_dev, port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) devlink_reload_enable(devlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return ret ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static struct device_attribute nsim_bus_dev_new_port_attr = __ATTR_WO(new_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) del_port_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct nsim_dev *nsim_dev = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct devlink *devlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned int port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* Prevent to use nsim_bus_dev before initialization. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (!smp_load_acquire(&nsim_bus_dev->init))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ret = kstrtouint(buf, 0, &port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) devlink = priv_to_devlink(nsim_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) mutex_lock(&nsim_bus_dev->nsim_bus_reload_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) devlink_reload_disable(devlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ret = nsim_dev_port_del(nsim_bus_dev, port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) devlink_reload_enable(devlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return ret ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static struct device_attribute nsim_bus_dev_del_port_attr = __ATTR_WO(del_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static struct attribute *nsim_bus_dev_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) &nsim_bus_dev_numvfs_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) &nsim_bus_dev_new_port_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) &nsim_bus_dev_del_port_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static const struct attribute_group nsim_bus_dev_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .attrs = nsim_bus_dev_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static const struct attribute_group *nsim_bus_dev_attr_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) &nsim_bus_dev_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static void nsim_bus_dev_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) nsim_bus_dev_vfs_disable(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct device_type nsim_bus_dev_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .groups = nsim_bus_dev_attr_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .release = nsim_bus_dev_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static struct nsim_bus_dev *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) nsim_bus_dev_new(unsigned int id, unsigned int port_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) new_device_store(struct bus_type *bus, const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct nsim_bus_dev *nsim_bus_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) unsigned int port_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) unsigned int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) err = sscanf(buf, "%u %u", &id, &port_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) switch (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) port_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (id > INT_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) pr_err("Value of \"id\" is too big.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pr_err("Format for adding new device is \"id port_count\" (uint uint).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) mutex_lock(&nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Prevent to use resource before initialization. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!smp_load_acquire(&nsim_bus_enable)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) nsim_bus_dev = nsim_bus_dev_new(id, port_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (IS_ERR(nsim_bus_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) err = PTR_ERR(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* Allow using nsim_bus_dev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) smp_store_release(&nsim_bus_dev->init, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) list_add_tail(&nsim_bus_dev->list, &nsim_bus_dev_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) mutex_unlock(&nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) mutex_unlock(&nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static BUS_ATTR_WO(new_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) del_device_store(struct bus_type *bus, const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct nsim_bus_dev *nsim_bus_dev, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) unsigned int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) err = sscanf(buf, "%u", &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) switch (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (id > INT_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) pr_err("Value of \"id\" is too big.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) pr_err("Format for deleting device is \"id\" (uint).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) mutex_lock(&nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* Prevent to use resource before initialization. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!smp_load_acquire(&nsim_bus_enable)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) mutex_unlock(&nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (nsim_bus_dev->dev.id != id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) list_del(&nsim_bus_dev->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) nsim_bus_dev_del(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mutex_unlock(&nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return !err ? count : err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static BUS_ATTR_WO(del_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static struct attribute *nsim_bus_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) &bus_attr_new_device.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) &bus_attr_del_device.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ATTRIBUTE_GROUPS(nsim_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int nsim_bus_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return nsim_dev_probe(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static int nsim_bus_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) nsim_dev_remove(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static int nsim_num_vf(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return nsim_bus_dev->num_vfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static struct bus_type nsim_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .dev_name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .bus_groups = nsim_bus_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .probe = nsim_bus_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .remove = nsim_bus_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .num_vf = nsim_num_vf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static struct nsim_bus_dev *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) nsim_bus_dev_new(unsigned int id, unsigned int port_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct nsim_bus_dev *nsim_bus_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (!nsim_bus_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) err = ida_alloc_range(&nsim_bus_dev_ids, id, id, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) goto err_nsim_bus_dev_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) nsim_bus_dev->dev.id = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) nsim_bus_dev->dev.bus = &nsim_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) nsim_bus_dev->dev.type = &nsim_bus_dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) nsim_bus_dev->port_count = port_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) nsim_bus_dev->initial_net = current->nsproxy->net_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) mutex_init(&nsim_bus_dev->nsim_bus_reload_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* Disallow using nsim_bus_dev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) smp_store_release(&nsim_bus_dev->init, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) err = device_register(&nsim_bus_dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto err_nsim_bus_dev_id_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return nsim_bus_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) err_nsim_bus_dev_id_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) err_nsim_bus_dev_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) kfree(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* Disallow using nsim_bus_dev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) smp_store_release(&nsim_bus_dev->init, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) device_unregister(&nsim_bus_dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) kfree(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static struct device_driver nsim_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .bus = &nsim_bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) int nsim_bus_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) err = bus_register(&nsim_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) err = driver_register(&nsim_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) goto err_bus_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* Allow using resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) smp_store_release(&nsim_bus_enable, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) err_bus_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) bus_unregister(&nsim_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) void nsim_bus_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct nsim_bus_dev *nsim_bus_dev, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* Disallow using resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) smp_store_release(&nsim_bus_enable, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) mutex_lock(&nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) list_del(&nsim_bus_dev->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) nsim_bus_dev_del(nsim_bus_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) mutex_unlock(&nsim_bus_dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) driver_unregister(&nsim_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) bus_unregister(&nsim_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }