// SPDX-License-Identifier: GPL-2.0
      /* Copyright (C) 2017 Netronome Systems, Inc.
       * Copyright (C) 2019 Mellanox Technologies. All rights reserved
       */
      
      #include <linux/device.h>
      #include <linux/idr.h>
      #include <linux/kernel.h>
      #include <linux/list.h>
      #include <linux/mutex.h>
      #include <linux/rtnetlink.h>
      #include <linux/slab.h>
      #include <linux/sysfs.h>
      
      #include "netdevsim.h"
      
      static DEFINE_IDA(nsim_bus_dev_ids);
      static LIST_HEAD(nsim_bus_dev_list);
      static DEFINE_MUTEX(nsim_bus_dev_list_lock);
      static bool nsim_bus_enable;
      
      static struct nsim_bus_dev *to_nsim_bus_dev(struct device *dev)
      {
              return container_of(dev, struct nsim_bus_dev, dev);
      }
      
      static int nsim_bus_dev_vfs_enable(struct nsim_bus_dev *nsim_bus_dev,
                                         unsigned int num_vfs)
      {
              nsim_bus_dev->vfconfigs = kcalloc(num_vfs,
                                                sizeof(struct nsim_vf_config),
                                                GFP_KERNEL | __GFP_NOWARN);
              if (!nsim_bus_dev->vfconfigs)
                      return -ENOMEM;
              nsim_bus_dev->num_vfs = num_vfs;
      
              return 0;
      }
      
      static void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev)
      {
              kfree(nsim_bus_dev->vfconfigs);
              nsim_bus_dev->vfconfigs = NULL;
              nsim_bus_dev->num_vfs = 0;
      }
      
      static ssize_t
      nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr,
                                const char *buf, size_t count)
      {
              struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
              unsigned int num_vfs;
              int ret;
      
              ret = kstrtouint(buf, 0, &num_vfs);
              if (ret)
                      return ret;