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