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        struct nsim_dev *nsim_dev;
  31        int err = 0;
  32
  33        if (nsim_bus_dev->max_vfs < num_vfs)
  34                return -ENOMEM;
  35
  36        if (!nsim_bus_dev->vfconfigs)
  37                return -ENOMEM;
  38        nsim_bus_dev->num_vfs = num_vfs;
  39
  40        nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
  41        if (nsim_esw_mode_is_switchdev(nsim_dev)) {
  42                err = nsim_esw_switchdev_enable(nsim_dev, NULL);
  43                if (err)
  44                        nsim_bus_dev->num_vfs = 0;
  45        }
  46
  47        return err;
  48}
  49
  50void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev)
  51{
  52        struct nsim_dev *nsim_dev;
  53
  54        nsim_bus_dev->num_vfs = 0;
  55        nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
  56        if (nsim_esw_mode_is_switchdev(nsim_dev))
  57                nsim_esw_legacy_enable(nsim_dev, NULL);
  58}
  59
  60static ssize_t
  61nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr,
  62                          const char *buf, size_t count)
  63{
  64        struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
  65        unsigned int num_vfs;
  66        int ret;
  67
  68        ret = kstrtouint(buf, 0, &num_vfs);
  69        if (ret)
  70                return ret;
  71
  72        mutex_lock(&nsim_bus_dev->vfs_lock);
  73        if (nsim_bus_dev->num_vfs == num_vfs)
  74                goto exit_good;
  75        if (nsim_bus_dev->num_vfs && num_vfs) {
  76                ret = -EBUSY;
  77                goto exit_unlock;
  78        }
  79
  80        if (num_vfs) {
  81                ret = nsim_bus_dev_vfs_enable(nsim_bus_dev, num_vfs);
  82                if (ret)
  83                        goto exit_unlock;
  84        } else {
  85                nsim_bus_dev_vfs_disable(nsim_bus_dev);
  86        }
  87exit_good:
  88        ret = count;
  89exit_unlock:
  90        mutex_unlock(&nsim_bus_dev->vfs_lock);
  91
  92        return ret;
  93}
  94
  95static ssize_t
  96nsim_bus_dev_numvfs_show(struct device *dev,
  97                         struct device_attribute *attr, char *buf)
  98{
  99        struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 100
 101        return sprintf(buf, "%u\n", nsim_bus_dev->num_vfs);
 102}
 103
 104static struct device_attribute nsim_bus_dev_numvfs_attr =
 105        __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
 106               nsim_bus_dev_numvfs_store);
 107
 108ssize_t nsim_bus_dev_max_vfs_read(struct file *file,
 109                                  char __user *data,
 110                                  size_t count, loff_t *ppos)
 111{
 112        struct nsim_bus_dev *nsim_bus_dev = file->private_data;
 113        char buf[11];
 114        ssize_t len;
 115
 116        len = snprintf(buf, sizeof(buf), "%u\n", nsim_bus_dev->max_vfs);
 117        if (len < 0)
 118                return len;
 119
 120        return simple_read_from_buffer(data, count, ppos, buf, len);
 121}
 122
 123ssize_t nsim_bus_dev_max_vfs_write(struct file *file,
 124                                   const char __user *data,
 125                                   size_t count, loff_t *ppos)
 126{
 127        struct nsim_bus_dev *nsim_bus_dev = file->private_data;
 128        struct nsim_vf_config *vfconfigs;
 129        ssize_t ret;
 130        char buf[10];
 131        u32 val;
 132
 133        if (*ppos != 0)
 134                return 0;
 135
 136        if (count >= sizeof(buf))
 137                return -ENOSPC;
 138
 139        mutex_lock(&nsim_bus_dev->vfs_lock);
 140        /* Reject if VFs are configured */
 141        if (nsim_bus_dev->num_vfs) {
 142                ret = -EBUSY;
 143                goto unlock;
 144        }
 145
 146        ret = copy_from_user(buf, data, count);
 147        if (ret) {
 148                ret = -EFAULT;
 149                goto unlock;
 150        }
 151
 152        buf[count] = '\0';
 153        ret = kstrtouint(buf, 10, &val);
 154        if (ret) {
 155                ret = -EIO;
 156                goto unlock;
 157        }
 158
 159        /* max_vfs limited by the maximum number of provided port indexes */
 160        if (val > NSIM_DEV_VF_PORT_INDEX_MAX - NSIM_DEV_VF_PORT_INDEX_BASE) {
 161                ret = -ERANGE;
 162                goto unlock;
 163        }
 164
 165        vfconfigs = kcalloc(val, sizeof(struct nsim_vf_config), GFP_KERNEL | __GFP_NOWARN);
 166        if (!vfconfigs) {
 167                ret = -ENOMEM;
 168                goto unlock;
 169        }
 170
 171        kfree(nsim_bus_dev->vfconfigs);
 172        nsim_bus_dev->vfconfigs = vfconfigs;
 173        nsim_bus_dev->max_vfs = val;
 174        *ppos += count;
 175        ret = count;
 176unlock:
 177        mutex_unlock(&nsim_bus_dev->vfs_lock);
 178        return ret;
 179}
 180
 181static ssize_t
 182new_port_store(struct device *dev, struct device_attribute *attr,
 183               const char *buf, size_t count)
 184{
 185        struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 186        unsigned int port_index;
 187        int ret;
 188
 189        /* Prevent to use nsim_bus_dev before initialization. */
 190        if (!smp_load_acquire(&nsim_bus_dev->init))
 191                return -EBUSY;
 192        ret = kstrtouint(buf, 0, &port_index);
 193        if (ret)
 194                return ret;
 195
 196        if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock))
 197                return -EBUSY;
 198
 199        if (nsim_bus_dev->in_reload) {
 200                mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
 201                return -EBUSY;
 202        }
 203
 204        ret = nsim_dev_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
 205        mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
 206        return ret ? ret : count;
 207}
 208
 209static struct device_attribute nsim_bus_dev_new_port_attr = __ATTR_WO(new_port);
 210
 211static ssize_t
 212del_port_store(struct device *dev, struct device_attribute *attr,
 213               const char *buf, size_t count)
 214{
 215        struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 216        unsigned int port_index;
 217        int ret;
 218
 219        /* Prevent to use nsim_bus_dev before initialization. */
 220        if (!smp_load_acquire(&nsim_bus_dev->init))
 221                return -EBUSY;
 222        ret = kstrtouint(buf, 0, &port_index);
 223        if (ret)
 224                return ret;
 225
 226        if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock))
 227                return -EBUSY;
 228
 229        if (nsim_bus_dev->in_reload) {
 230                mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
 231                return -EBUSY;
 232        }
 233
 234        ret = nsim_dev_port_del(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
 235        mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
 236        return ret ? ret : count;
 237}
 238
 239static struct device_attribute nsim_bus_dev_del_port_attr = __ATTR_WO(del_port);
 240
 241static struct attribute *nsim_bus_dev_attrs[] = {
 242        &nsim_bus_dev_numvfs_attr.attr,
 243        &nsim_bus_dev_new_port_attr.attr,
 244        &nsim_bus_dev_del_port_attr.attr,
 245        NULL,
 246};
 247
 248static const struct attribute_group nsim_bus_dev_attr_group = {
 249        .attrs = nsim_bus_dev_attrs,
 250};
 251
 252static const struct attribute_group *nsim_bus_dev_attr_groups[] = {
 253        &nsim_bus_dev_attr_group,
 254        NULL,
 255};
 256
 257static void nsim_bus_dev_release(struct device *dev)
 258{
 259}
 260
 261static struct device_type nsim_bus_dev_type = {
 262        .groups = nsim_bus_dev_attr_groups,
 263        .release = nsim_bus_dev_release,
 264};
 265
 266static struct nsim_bus_dev *
 267nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queues);
 268
 269static ssize_t
 270new_device_store(struct bus_type *bus, const char *buf, size_t count)
 271{
 272        unsigned int id, port_count, num_queues;
 273        struct nsim_bus_dev *nsim_bus_dev;
 274        int err;
 275
 276        err = sscanf(buf, "%u %u %u", &id, &port_count, &num_queues);
 277        switch (err) {
 278        case 1:
 279                port_count = 1;
 280                fallthrough;
 281        case 2:
 282                num_queues = 1;
 283                fallthrough;
 284        case 3:
 285                if (id > INT_MAX) {
 286                        pr_err("Value of \"id\" is too big.\n");
 287                        return -EINVAL;
 288                }
 289                break;
 290        default:
 291                pr_err("Format for adding new device is \"id port_count num_queues\" (uint uint unit).\n");
 292                return -EINVAL;
 293        }
 294
 295        mutex_lock(&nsim_bus_dev_list_lock);
 296        /* Prevent to use resource before initialization. */
 297        if (!smp_load_acquire(&nsim_bus_enable)) {
 298                err = -EBUSY;
 299                goto err;
 300        }
 301
 302        nsim_bus_dev = nsim_bus_dev_new(id, port_count, num_queues);
 303        if (IS_ERR(nsim_bus_dev)) {
 304                err = PTR_ERR(nsim_bus_dev);
 305                goto err;
 306        }
 307
 308        /* Allow using nsim_bus_dev */
 309        smp_store_release(&nsim_bus_dev->init, true);
 310
 311        list_add_tail(&nsim_bus_dev->list, &nsim_bus_dev_list);
 312        mutex_unlock(&nsim_bus_dev_list_lock);
 313
 314        return count;
 315err:
 316        mutex_unlock(&nsim_bus_dev_list_lock);
 317        return err;
 318}
 319static BUS_ATTR_WO(new_device);
 320
 321static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev);
 322
 323static ssize_t
 324del_device_store(struct bus_type *bus, const char *buf, size_t count)
 325{
 326        struct nsim_bus_dev *nsim_bus_dev, *tmp;
 327        unsigned int id;
 328        int err;
 329
 330        err = sscanf(buf, "%u", &id);
 331        switch (err) {
 332        case 1:
 333                if (id > INT_MAX) {
 334                        pr_err("Value of \"id\" is too big.\n");
 335                        return -EINVAL;
 336                }
 337                break;
 338        default:
 339                pr_err("Format for deleting device is \"id\" (uint).\n");
 340                return -EINVAL;
 341        }
 342
 343        err = -ENOENT;
 344        mutex_lock(&nsim_bus_dev_list_lock);
 345        /* Prevent to use resource before initialization. */
 346        if (!smp_load_acquire(&nsim_bus_enable)) {
 347                mutex_unlock(&nsim_bus_dev_list_lock);
 348                return -EBUSY;
 349        }
 350        list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) {
 351                if (nsim_bus_dev->dev.id != id)
 352                        continue;
 353                list_del(&nsim_bus_dev->list);
 354                nsim_bus_dev_del(nsim_bus_dev);
 355                err = 0;
 356                break;
 357        }
 358        mutex_unlock(&nsim_bus_dev_list_lock);
 359        return !err ? count : err;
 360}
 361static BUS_ATTR_WO(del_device);
 362
 363static struct attribute *nsim_bus_attrs[] = {
 364        &bus_attr_new_device.attr,
 365        &bus_attr_del_device.attr,
 366        NULL
 367};
 368ATTRIBUTE_GROUPS(nsim_bus);
 369
 370static int nsim_bus_probe(struct device *dev)
 371{
 372        struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 373
 374        return nsim_dev_probe(nsim_bus_dev);
 375}
 376
 377static void nsim_bus_remove(struct device *dev)
 378{
 379        struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 380
 381        nsim_dev_remove(nsim_bus_dev);
 382}
 383
 384static int nsim_num_vf(struct device *dev)
 385{
 386        struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
 387
 388        return nsim_bus_dev->num_vfs;
 389}
 390
 391static struct bus_type nsim_bus = {
 392        .name           = DRV_NAME,
 393        .dev_name       = DRV_NAME,
 394        .bus_groups     = nsim_bus_groups,
 395        .probe          = nsim_bus_probe,
 396        .remove         = nsim_bus_remove,
 397        .num_vf         = nsim_num_vf,
 398};
 399
 400#define NSIM_BUS_DEV_MAX_VFS 4
 401
 402static struct nsim_bus_dev *
 403nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queues)
 404{
 405        struct nsim_bus_dev *nsim_bus_dev;
 406        int err;
 407
 408        nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL);
 409        if (!nsim_bus_dev)
 410                return ERR_PTR(-ENOMEM);
 411
 412        err = ida_alloc_range(&nsim_bus_dev_ids, id, id, GFP_KERNEL);
 413        if (err < 0)
 414                goto err_nsim_bus_dev_free;
 415        nsim_bus_dev->dev.id = err;
 416        nsim_bus_dev->dev.bus = &nsim_bus;
 417        nsim_bus_dev->dev.type = &nsim_bus_dev_type;
 418        nsim_bus_dev->port_count = port_count;
 419        nsim_bus_dev->num_queues = num_queues;
 420        nsim_bus_dev->initial_net = current->nsproxy->net_ns;
 421        nsim_bus_dev->max_vfs = NSIM_BUS_DEV_MAX_VFS;
 422        mutex_init(&nsim_bus_dev->nsim_bus_reload_lock);
 423        mutex_init(&nsim_bus_dev->vfs_lock);
 424        /* Disallow using nsim_bus_dev */
 425        smp_store_release(&nsim_bus_dev->init, false);
 426
 427        nsim_bus_dev->vfconfigs = kcalloc(nsim_bus_dev->max_vfs,
 428                                          sizeof(struct nsim_vf_config),
 429                                          GFP_KERNEL | __GFP_NOWARN);
 430        if (!nsim_bus_dev->vfconfigs) {
 431                err = -ENOMEM;
 432                goto err_nsim_bus_dev_id_free;
 433        }
 434
 435        err = device_register(&nsim_bus_dev->dev);
 436        if (err)
 437                goto err_nsim_vfs_free;
 438
 439        return nsim_bus_dev;
 440
 441err_nsim_vfs_free:
 442        kfree(nsim_bus_dev->vfconfigs);
 443err_nsim_bus_dev_id_free:
 444        ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
 445err_nsim_bus_dev_free:
 446        kfree(nsim_bus_dev);
 447        return ERR_PTR(err);
 448}
 449
 450static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev)
 451{
 452        /* Disallow using nsim_bus_dev */
 453        smp_store_release(&nsim_bus_dev->init, false);
 454        device_unregister(&nsim_bus_dev->dev);
 455        ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
 456        kfree(nsim_bus_dev->vfconfigs);
 457        kfree(nsim_bus_dev);
 458}
 459
 460static struct device_driver nsim_driver = {
 461        .name           = DRV_NAME,
 462        .bus            = &nsim_bus,
 463        .owner          = THIS_MODULE,
 464};
 465
 466int nsim_bus_init(void)
 467{
 468        int err;
 469
 470        err = bus_register(&nsim_bus);
 471        if (err)
 472                return err;
 473        err = driver_register(&nsim_driver);
 474        if (err)
 475                goto err_bus_unregister;
 476        /* Allow using resources */
 477        smp_store_release(&nsim_bus_enable, true);
 478        return 0;
 479
 480err_bus_unregister:
 481        bus_unregister(&nsim_bus);
 482        return err;
 483}
 484
 485void nsim_bus_exit(void)
 486{
 487        struct nsim_bus_dev *nsim_bus_dev, *tmp;
 488
 489        /* Disallow using resources */
 490        smp_store_release(&nsim_bus_enable, false);
 491
 492        mutex_lock(&nsim_bus_dev_list_lock);
 493        list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) {
 494                list_del(&nsim_bus_dev->list);
 495                nsim_bus_dev_del(nsim_bus_dev);
 496        }
 497        mutex_unlock(&nsim_bus_dev_list_lock);
 498
 499        driver_unregister(&nsim_driver);
 500        bus_unregister(&nsim_bus);
 501}
 502