diff mbox series

[net-next,2/7] netdevsim: Add support for add and delete PCI SF port

Message ID 20210206125551.8616-3-parav@nvidia.com
State Superseded
Headers show
Series netdevsim port add, delete support | expand

Commit Message

Parav Pandit Feb. 6, 2021, 12:55 p.m. UTC
Simulate PCI SF ports. Allow user to create one or more PCI SF ports.

Examples:

echo "10 1" > /sys/bus/netdevsim/new_device

Add PCI PF port:
$ devlink port add netdevsim/netdevsim10 flavour pcipf pfnum 2
netdevsim/netdevsim10/1: type eth netdev eth1 flavour pcipf controller 0 pfnum 2 external false splittable false

Add PCI SF port where port index and sfnum are auto assigned by driver.

$ devlink port add netdevsim/netdevsim10 flavour pcisf pfnum 2
netdevsim/netdevsim10/2: type eth netdev eth2 flavour pcisf controller 0 pfnum 2 sfnum 0 splittable false

Show devlink ports:
$ devlink port show
netdevsim/netdevsim10/0: type eth netdev eth0 flavour physical port 1 splittable false
netdevsim/netdevsim10/1: type eth netdev eth1 flavour pcipf controller 0 pfnum 2 external false splittable false
netdevsim/netdevsim10/2: type eth netdev eth2 flavour pcisf controller 0 pfnum 2 sfnum 0 splittable false

Create a PCI SF port whose port index and SF number are assigned by
the user.

$ devlink port add netdevsim/netdevsim10/66 flavour pcisf pfnum 2 sfnum 66
netdevsim/netdevsim10/66: type eth netdev eth3 flavour pcisf controller 0 pfnum 2 sfnum 66 splittable false

Delete PCI SF and PF ports:
$ devlink port del netdevsim/netdevsim10/66
$ devlink port del netdevsim/netdevsim10/2
$ devlink port del netdevsim/netdevsim10/1

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/net/netdevsim/netdevsim.h     |  1 +
 drivers/net/netdevsim/port_function.c | 99 ++++++++++++++++++++++++++-
 2 files changed, 97 insertions(+), 3 deletions(-)

Comments

kernel test robot Feb. 6, 2021, 5:42 p.m. UTC | #1
Hi Parav,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Parav-Pandit/netdevsim-port-add-delete-support/20210206-210153
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 6626a0266566c5aea16178c5e6cd7fc4db3f2f56
config: x86_64-randconfig-a004-20210206 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project c9439ca36342fb6013187d0a69aef92736951476)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/980b8cbe1c29602278397d53732cc258b1d62416
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Parav-Pandit/netdevsim-port-add-delete-support/20210206-210153
        git checkout 980b8cbe1c29602278397d53732cc258b1d62416
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from drivers/net/netdevsim/port_function.c:7:
   drivers/net/netdevsim/netdevsim.h:318:23: warning: declaration of 'struct devlink_port_new_attrs' will not be visible outside of this function [-Wvisibility]
                                 const struct devlink_port_new_attrs *attrs,
                                              ^
   drivers/net/netdevsim/port_function.c:54:20: warning: declaration of 'struct devlink_port_new_attrs' will not be visible outside of this function [-Wvisibility]
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:74:23: error: incomplete definition of type 'struct devlink_port_new_attrs'
           port->flavour = attrs->flavour;
                           ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:76:11: error: incomplete definition of type 'struct devlink_port_new_attrs'
           if (attrs->port_index_valid)
               ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:78:16: error: incomplete definition of type 'struct devlink_port_new_attrs'
                                         attrs->port_index,
                                         ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:79:16: error: incomplete definition of type 'struct devlink_port_new_attrs'
                                         attrs->port_index, GFP_KERNEL);
                                         ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:91:16: error: incomplete definition of type 'struct devlink_port_new_attrs'
                                         attrs->pfnum, attrs->pfnum,
                                         ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:91:30: error: incomplete definition of type 'struct devlink_port_new_attrs'
                                         attrs->pfnum, attrs->pfnum,
                                                       ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
>> drivers/net/netdevsim/port_function.c:97:7: error: use of undeclared identifier 'DEVLINK_PORT_FLAVOUR_PCI_SF'
           case DEVLINK_PORT_FLAVOUR_PCI_SF:
                ^
   drivers/net/netdevsim/port_function.c:98:12: error: incomplete definition of type 'struct devlink_port_new_attrs'
                   if (attrs->sfnum_valid)
                       ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:99:63: error: incomplete definition of type 'struct devlink_port_new_attrs'
                           ret = ida_alloc_range(&dev->port_functions.sfnum_ida, attrs->sfnum,
                                                                                 ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:100:17: error: incomplete definition of type 'struct devlink_port_new_attrs'
                                                 attrs->sfnum, GFP_KERNEL);
                                                 ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:106:22: error: incomplete definition of type 'struct devlink_port_new_attrs'
                   port->pfnum = attrs->pfnum;
                                 ~~~~~^
   drivers/net/netdevsim/port_function.c:54:20: note: forward declaration of 'struct devlink_port_new_attrs'
                              const struct devlink_port_new_attrs *attrs)
                                           ^
   drivers/net/netdevsim/port_function.c:131:7: error: use of undeclared identifier 'DEVLINK_PORT_FLAVOUR_PCI_SF'
           case DEVLINK_PORT_FLAVOUR_PCI_SF:
                ^
   drivers/net/netdevsim/port_function.c:151:19: warning: declaration of 'struct devlink_port_new_attrs' will not be visible outside of this function [-Wvisibility]
                             const struct devlink_port_new_attrs *attrs)
                                          ^
   drivers/net/netdevsim/port_function.c:156:12: error: incomplete definition of type 'struct devlink_port_new_attrs'
                   if (attrs->port_index_valid &&
                       ~~~~~^
   drivers/net/netdevsim/port_function.c:151:19: note: forward declaration of 'struct devlink_port_new_attrs'
                             const struct devlink_port_new_attrs *attrs)
                                          ^
   drivers/net/netdevsim/port_function.c:157:31: error: incomplete definition of type 'struct devlink_port_new_attrs'
                       tmp->port_index == attrs->port_index)
                                          ~~~~~^
   drivers/net/netdevsim/port_function.c:151:19: note: forward declaration of 'struct devlink_port_new_attrs'
                             const struct devlink_port_new_attrs *attrs)
                                          ^
   drivers/net/netdevsim/port_function.c:159:12: error: incomplete definition of type 'struct devlink_port_new_attrs'
                   if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF &&
                       ~~~~~^
   drivers/net/netdevsim/port_function.c:151:19: note: forward declaration of 'struct devlink_port_new_attrs'
                             const struct devlink_port_new_attrs *attrs)
                                          ^
   drivers/net/netdevsim/port_function.c:161:26: error: incomplete definition of type 'struct devlink_port_new_attrs'
                       tmp->pfnum == attrs->pfnum)
                                     ~~~~~^
   drivers/net/netdevsim/port_function.c:151:19: note: forward declaration of 'struct devlink_port_new_attrs'
                             const struct devlink_port_new_attrs *attrs)
                                          ^
   drivers/net/netdevsim/port_function.c:164:12: error: incomplete definition of type 'struct devlink_port_new_attrs'
                   if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF &&
                       ~~~~~^
   drivers/net/netdevsim/port_function.c:151:19: note: forward declaration of 'struct devlink_port_new_attrs'
                             const struct devlink_port_new_attrs *attrs)
                                          ^
   drivers/net/netdevsim/port_function.c:166:12: error: incomplete definition of type 'struct devlink_port_new_attrs'
                       attrs->sfnum_valid &&
                       ~~~~~^
   drivers/net/netdevsim/port_function.c:151:19: note: forward declaration of 'struct devlink_port_new_attrs'
                             const struct devlink_port_new_attrs *attrs)
                                          ^
   drivers/net/netdevsim/port_function.c:167:26: error: incomplete definition of type 'struct devlink_port_new_attrs'
                       tmp->sfnum == attrs->sfnum && tmp->pfnum == attrs->pfnum)
                                     ~~~~~^
   drivers/net/netdevsim/port_function.c:151:19: note: forward declaration of 'struct devlink_port_new_attrs'
                             const struct devlink_port_new_attrs *attrs)
                                          ^
   fatal error: too many errors emitted, stopping now [-ferror-limit=]
   3 warnings and 20 errors generated.


vim +/DEVLINK_PORT_FLAVOUR_PCI_SF +97 drivers/net/netdevsim/port_function.c

    51	
    52	static struct nsim_port_fn *
    53	nsim_devlink_port_fn_alloc(struct nsim_dev *dev,
    54				   const struct devlink_port_new_attrs *attrs)
    55	{
    56		struct nsim_bus_dev *nsim_bus_dev = dev->nsim_bus_dev;
    57		struct nsim_port_fn *port;
    58		struct net_device *netdev;
    59		int ret;
    60	
    61		netdev = alloc_netdev(sizeof(*port), "eth%d", NET_NAME_UNKNOWN,
    62				      nsim_port_fn_ndev_setup);
    63		if (!netdev)
    64			return ERR_PTR(-ENOMEM);
    65	
    66		dev_net_set(netdev, nsim_dev_net(dev));
    67		netdev->netdev_ops = &nsim_netdev_ops;
    68		nsim_bus_dev = dev->nsim_bus_dev;
    69		SET_NETDEV_DEV(netdev, &nsim_bus_dev->dev);
    70	
    71		port = netdev_priv(netdev);
    72		memset(port, 0, sizeof(*port));
    73		port->netdev = netdev;
    74		port->flavour = attrs->flavour;
    75	
    76		if (attrs->port_index_valid)
    77			ret = ida_alloc_range(&dev->port_functions.ida,
    78					      attrs->port_index,
    79					      attrs->port_index, GFP_KERNEL);
    80		else
    81			ret = ida_alloc_min(&dev->port_functions.ida,
    82					    nsim_bus_dev->port_count, GFP_KERNEL);
    83		if (ret < 0)
    84			goto port_ida_err;
    85	
    86		port->port_index = ret;
    87	
    88		switch (port->flavour) {
    89		case DEVLINK_PORT_FLAVOUR_PCI_PF:
    90			ret = ida_alloc_range(&dev->port_functions.pfnum_ida,
    91					      attrs->pfnum, attrs->pfnum,
    92					      GFP_KERNEL);
    93			if (ret < 0)
    94				goto fn_ida_err;
    95			port->pfnum = ret;
    96			break;
  > 97		case DEVLINK_PORT_FLAVOUR_PCI_SF:
    98			if (attrs->sfnum_valid)
    99				ret = ida_alloc_range(&dev->port_functions.sfnum_ida, attrs->sfnum,
   100						      attrs->sfnum, GFP_KERNEL);
   101			else
   102				ret = ida_alloc(&dev->port_functions.sfnum_ida, GFP_KERNEL);
   103			if (ret < 0)
   104				goto fn_ida_err;
   105			port->sfnum = ret;
   106			port->pfnum = attrs->pfnum;
   107			break;
   108		default:
   109			break;
   110		}
   111		/* refcount_t is not needed as port is protected by port_functions.mutex.
   112		 * This count is to keep track of how many SF ports are attached a PF port.
   113		 */
   114		port->refcount = 1;
   115		return port;
   116	
   117	fn_ida_err:
   118		ida_simple_remove(&dev->port_functions.ida, port->port_index);
   119	port_ida_err:
   120		free_netdev(netdev);
   121		return ERR_PTR(ret);
   122	}
   123	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 31beddede0f2..efa7c08d842a 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -233,6 +233,7 @@  struct nsim_dev {
 		struct list_head head;
 		struct ida ida;
 		struct ida pfnum_ida;
+		struct ida sfnum_ida;
 		struct mutex disable_mutex; /* protects port deletion
 					     * by driver unload context
 					     */
diff --git a/drivers/net/netdevsim/port_function.c b/drivers/net/netdevsim/port_function.c
index a957b754ef92..a2f62a609e9b 100644
--- a/drivers/net/netdevsim/port_function.c
+++ b/drivers/net/netdevsim/port_function.c
@@ -9,9 +9,12 @@ 
 struct nsim_port_fn {
 	struct devlink_port dl_port;
 	struct net_device *netdev;
+	struct nsim_port_fn *pf_pfn;
 	struct list_head list;
 	unsigned int port_index;
 	enum devlink_port_flavour flavour;
+	int refcount; /* Counts how many sf ports are bound attached to this pf port. */
+	u32 sfnum;
 	u16 pfnum;
 };
 
@@ -91,9 +94,24 @@  nsim_devlink_port_fn_alloc(struct nsim_dev *dev,
 			goto fn_ida_err;
 		port->pfnum = ret;
 		break;
+	case DEVLINK_PORT_FLAVOUR_PCI_SF:
+		if (attrs->sfnum_valid)
+			ret = ida_alloc_range(&dev->port_functions.sfnum_ida, attrs->sfnum,
+					      attrs->sfnum, GFP_KERNEL);
+		else
+			ret = ida_alloc(&dev->port_functions.sfnum_ida, GFP_KERNEL);
+		if (ret < 0)
+			goto fn_ida_err;
+		port->sfnum = ret;
+		port->pfnum = attrs->pfnum;
+		break;
 	default:
 		break;
 	}
+	/* refcount_t is not needed as port is protected by port_functions.mutex.
+	 * This count is to keep track of how many SF ports are attached a PF port.
+	 */
+	port->refcount = 1;
 	return port;
 
 fn_ida_err:
@@ -110,6 +128,9 @@  nsim_devlink_port_fn_free(struct nsim_dev *dev, struct nsim_port_fn *port)
 	case DEVLINK_PORT_FLAVOUR_PCI_PF:
 		ida_simple_remove(&dev->port_functions.pfnum_ida, port->pfnum);
 		break;
+	case DEVLINK_PORT_FLAVOUR_PCI_SF:
+		ida_simple_remove(&dev->port_functions.sfnum_ida, port->sfnum);
+		break;
 	default:
 		break;
 	}
@@ -139,6 +160,12 @@  nsim_dev_port_port_exists(struct nsim_dev *nsim_dev,
 		    tmp->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF &&
 		    tmp->pfnum == attrs->pfnum)
 			return true;
+
+		if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF &&
+		    tmp->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF &&
+		    attrs->sfnum_valid &&
+		    tmp->sfnum == attrs->sfnum && tmp->pfnum == attrs->pfnum)
+			return true;
 	}
 	return false;
 }
@@ -153,20 +180,72 @@  nsim_dev_devlink_port_index_lookup(const struct nsim_dev *nsim_dev,
 	list_for_each_entry(port, &nsim_dev->port_functions.head, list) {
 		if (port->port_index != port_index)
 			continue;
+		if (port->refcount > 1) {
+			NL_SET_ERR_MSG_MOD(extack, "Port is in use");
+			return ERR_PTR(-EBUSY);
+		}
 		return port;
 	}
 	NL_SET_ERR_MSG_MOD(extack, "User created port not found");
 	return ERR_PTR(-ENOENT);
 }
 
+static struct nsim_port_fn *
+pf_port_get(struct nsim_dev *nsim_dev, struct nsim_port_fn *port)
+{
+	struct nsim_port_fn *tmp;
+
+	/* PF port addition doesn't need a parent. */
+	if (port->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF)
+		return NULL;
+
+	list_for_each_entry(tmp, &nsim_dev->port_functions.head, list) {
+		if (tmp->flavour != DEVLINK_PORT_FLAVOUR_PCI_PF ||
+		    tmp->pfnum != port->pfnum)
+			continue;
+
+		if (tmp->refcount + 1 == INT_MAX)
+			return ERR_PTR(-ENOSPC);
+
+		port->pf_pfn = tmp;
+		tmp->refcount++;
+		return tmp;
+	}
+	return ERR_PTR(-ENOENT);
+}
+
+static void pf_port_put(struct nsim_port_fn *port)
+{
+	if (port->pf_pfn) {
+		port->pf_pfn->refcount--;
+		WARN_ON(port->pf_pfn->refcount < 0);
+	}
+	port->refcount--;
+	WARN_ON(port->refcount != 0);
+}
+
 static int nsim_devlink_port_fn_add(struct devlink *devlink,
 				    struct nsim_dev *nsim_dev,
 				    struct nsim_port_fn *port,
 				    struct netlink_ext_ack *extack)
 {
+	struct nsim_port_fn *pf_pfn;
 	int err;
 
-	list_add(&port->list, &nsim_dev->port_functions.head);
+	/* Keep all PF ports at the start, so that when driver is unloaded
+	 * All SF ports from the end of the list can be removed first.
+	 */
+	if (port->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF)
+		list_add(&port->list, &nsim_dev->port_functions.head);
+	else
+		list_add_tail(&port->list, &nsim_dev->port_functions.head);
+
+	pf_pfn = pf_port_get(nsim_dev, port);
+	if (IS_ERR(pf_pfn)) {
+		NL_SET_ERR_MSG_MOD(extack, "Fail to get pf port");
+		err = PTR_ERR(pf_pfn);
+		goto pf_err;
+	}
 
 	err = devlink_port_register(devlink, &port->dl_port, port->port_index);
 	if (err)
@@ -183,6 +262,8 @@  static int nsim_devlink_port_fn_add(struct devlink *devlink,
 	devlink_port_type_clear(&port->dl_port);
 	devlink_port_unregister(&port->dl_port);
 reg_err:
+	pf_port_put(port);
+pf_err:
 	list_del(&port->list);
 	return err;
 }
@@ -194,13 +275,15 @@  static void nsim_devlink_port_fn_del(struct nsim_dev *nsim_dev,
 	unregister_netdev(port->netdev);
 	devlink_port_unregister(&port->dl_port);
 	list_del(&port->list);
+	pf_port_put(port);
 }
 
 static bool
 nsim_dev_port_flavour_supported(const struct nsim_dev *nsim_dev,
 				const struct devlink_port_new_attrs *attrs)
 {
-	return attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF;
+	return attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF ||
+	       attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF;
 }
 
 int nsim_dev_devlink_port_new(struct devlink *devlink,
@@ -245,7 +328,12 @@  int nsim_dev_devlink_port_new(struct devlink *devlink,
 	       nsim_dev->switch_id.id_len);
 	port->dl_port.attrs.switch_id.id_len = nsim_dev->switch_id.id_len;
 
-	devlink_port_attrs_pci_pf_set(&port->dl_port, 0, port->pfnum, false);
+	if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF)
+		devlink_port_attrs_pci_pf_set(&port->dl_port, 0,
+					      port->pfnum, false);
+	else
+		devlink_port_attrs_pci_sf_set(&port->dl_port, 0, port->pfnum,
+					      port->sfnum);
 
 	err = nsim_devlink_port_fn_add(devlink, nsim_dev, port, extack);
 	if (err)
@@ -300,10 +388,13 @@  void nsim_dev_port_fn_init(struct nsim_dev *nsim_dev)
 	INIT_LIST_HEAD(&nsim_dev->port_functions.head);
 	ida_init(&nsim_dev->port_functions.ida);
 	ida_init(&nsim_dev->port_functions.pfnum_ida);
+	ida_init(&nsim_dev->port_functions.sfnum_ida);
 }
 
 void nsim_dev_port_fn_exit(struct nsim_dev *nsim_dev)
 {
+	WARN_ON(!ida_is_empty(&nsim_dev->port_functions.sfnum_ida));
+	ida_destroy(&nsim_dev->port_functions.sfnum_ida);
 	WARN_ON(!ida_is_empty(&nsim_dev->port_functions.pfnum_ida));
 	ida_destroy(&nsim_dev->port_functions.pfnum_ida);
 	WARN_ON(!ida_is_empty(&nsim_dev->port_functions.ida));
@@ -332,6 +423,8 @@  void nsim_dev_port_fn_disable(struct nsim_dev *nsim_dev)
 	 * commands have completed, so it is safe to delete all user created
 	 * ports.
 	 */
+
+	/* Remove SF ports first, followed by PF ports. */
 	list_for_each_entry_safe_reverse(port, tmp,
 					 &nsim_dev->port_functions.head, list) {
 		nsim_devlink_port_fn_del(nsim_dev, port);