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