From patchwork Thu Sep 17 08:17:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1365972 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.a=rsa-sha256 header.s=n1 header.b=gOT/zYP9; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BsVNf20lrz9sRf for ; Thu, 17 Sep 2020 18:23:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726423AbgIQIXp (ORCPT ); Thu, 17 Sep 2020 04:23:45 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:3195 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726185AbgIQIW4 (ORCPT ); Thu, 17 Sep 2020 04:22:56 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 01:16:19 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 01:17:47 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 01:17:47 -0700 Received: from sw-mtx-036.mtx.labs.mlnx (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 17 Sep 2020 08:17:46 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next 1/8] devlink: Introduce PCI SF port flavour and port attribute Date: Thu, 17 Sep 2020 11:17:24 +0300 Message-ID: <20200917081731.8363-2-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917081731.8363-1-parav@nvidia.com> References: <20200917081731.8363-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL101.nvidia.com (172.20.187.10) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600330579; bh=jpeVIePcr4P/WgqPcPWzoK9/7uEOJGAmBj2FJlwT4cw=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding: Content-Type:X-Originating-IP:X-ClientProxiedBy; b=gOT/zYP9+0DvllxaOzeCZLWkvilG4Ws9p6Ir1+ySUC1ANgAoA+kaU/JYExehCiOE5 qobEOdX31RepBVtqo4MLtfNEt5D7U0karkAEq5404PxIXQoc6k3IRXsaBhEmpWr8xY ypsxutKbznWhX04eALfq5aMHGPkc2cBPpjkPHqR5JL++5vcRzY8iR3FlVEW64RAmKS IUG3J80hwc/mXaCKGvqyLXt5YBz4DGKAUQtkIEzXAnaS0rWjH9+fWoX0c5Ww10mg2W JUpXMZWraviArQ2HN10FCzT9BgdSg2sIt/60MKqcrCE1wFvPgrPMypN1+j3jefFii/ u/yf7zdXZUlaA== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org A PCI sub-function (SF) represents a portion of the device similar to PCI VF. In an eswitch, PCI SF may have port which is normally represented using a representor netdevice. To have better visibility of eswitch port, its association with SF, and its representor netdevice, introduce a PCI SF port flavour. When devlink port flavour is PCI SF, fill up PCI SF attributes of the port. Extend port name creation using PCI PF and SF number scheme on best effort basis, so that vendor drivers can skip defining their own scheme. An example view of a PCI SF port. $ devlink port show netdevsim/netdevsim10/2 netdevsim/netdevsim10/2: type eth netdev eni10npf0sf44 flavour pcisf controller 0 pfnum 0 sfnum 44 external false splittable false function: hw_addr 00:00:00:00:00:00 devlink port show netdevsim/netdevsim10/2 -jp { "port": { "netdevsim/netdevsim10/2": { "type": "eth", "netdev": "eni10npf0sf44", "flavour": "pcisf", "controller": 0, "pfnum": 0, "sfnum": 44, "external": false, "splittable": false, "function": { "hw_addr": "00:00:00:00:00:00" } } } } Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko --- include/net/devlink.h | 17 +++++++++++++++++ include/uapi/linux/devlink.h | 7 +++++++ net/core/devlink.c | 37 ++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/include/net/devlink.h b/include/net/devlink.h index 48b1c1ef1ebd..1edb558125b0 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -83,6 +83,20 @@ struct devlink_port_pci_vf_attrs { u8 external:1; }; +/** + * struct devlink_port_pci_sf_attrs - devlink port's PCI SF attributes + * @controller: Associated controller number + * @pf: Associated PCI PF number for this port. + * @sf: Associated PCI SF for of the PCI PF for this port. + * @external: when set, indicates if a port is for an external controller + */ +struct devlink_port_pci_sf_attrs { + u32 controller; + u16 pf; + u32 sf; + u8 external:1; +}; + /** * struct devlink_port_attrs - devlink port object * @flavour: flavour of the port @@ -104,6 +118,7 @@ struct devlink_port_attrs { struct devlink_port_phys_attrs phys; struct devlink_port_pci_pf_attrs pci_pf; struct devlink_port_pci_vf_attrs pci_vf; + struct devlink_port_pci_sf_attrs pci_sf; }; }; @@ -1230,6 +1245,8 @@ void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 contro u16 pf, bool external); void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller, u16 pf, u16 vf, bool external); +void devlink_port_attrs_pci_sf_set(struct devlink_port *devlink_port, u32 controller, + u16 pf, u32 sf, bool external); int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, u32 size, u16 ingress_pools_count, u16 egress_pools_count, u16 ingress_tc_count, diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index 631f5bdf1707..09c41b9ce407 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -195,6 +195,11 @@ enum devlink_port_flavour { * port that faces the PCI VF. */ DEVLINK_PORT_FLAVOUR_VIRTUAL, /* Any virtual port facing the user. */ + + DEVLINK_PORT_FLAVOUR_PCI_SF, /* Represents eswitch port + * for the PCI SF. It is an internal + * port that faces the PCI SF. + */ }; enum devlink_param_cmode { @@ -462,6 +467,8 @@ enum devlink_attr { DEVLINK_ATTR_PORT_EXTERNAL, /* u8 */ DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, /* u32 */ + + DEVLINK_ATTR_PORT_PCI_SF_NUMBER, /* u32 */ /* add new attributes above here, update the policy in devlink.c */ __DEVLINK_ATTR_MAX, diff --git a/net/core/devlink.c b/net/core/devlink.c index e5b71f3c2d4d..fada660fd515 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -539,6 +539,15 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg, if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_vf.external)) return -EMSGSIZE; break; + case DEVLINK_PORT_FLAVOUR_PCI_SF: + if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, + attrs->pci_sf.controller) || + nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_sf.pf) || + nla_put_u32(msg, DEVLINK_ATTR_PORT_PCI_SF_NUMBER, attrs->pci_sf.sf)) + return -EMSGSIZE; + if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_vf.external)) + return -EMSGSIZE; + break; case DEVLINK_PORT_FLAVOUR_PHYSICAL: case DEVLINK_PORT_FLAVOUR_CPU: case DEVLINK_PORT_FLAVOUR_DSA: @@ -7808,6 +7817,31 @@ void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 contro } EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set); +/** + * devlink_port_attrs_pci_sf_set - Set PCI SF port attributes + * + * @devlink_port: devlink port + * @controller: associated controller number for the devlink port instance + * @pf: associated PF for the devlink port instance + * @sf: associated SF of a PF for the devlink port instance + * @external: indicates if the port is for an external controller + */ +void devlink_port_attrs_pci_sf_set(struct devlink_port *devlink_port, u32 controller, + u16 pf, u32 sf, bool external) +{ + struct devlink_port_attrs *attrs = &devlink_port->attrs; + int ret; + + ret = __devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PCI_SF); + if (ret) + return; + attrs->pci_sf.controller = controller; + attrs->pci_sf.pf = pf; + attrs->pci_sf.sf = sf; + attrs->pci_sf.external = external; +} +EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_sf_set); + static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, char *name, size_t len) { @@ -7855,6 +7889,9 @@ static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, n = snprintf(name, len, "pf%uvf%u", attrs->pci_vf.pf, attrs->pci_vf.vf); break; + case DEVLINK_PORT_FLAVOUR_PCI_SF: + n = snprintf(name, len, "pf%usf%u", attrs->pci_sf.pf, attrs->pci_sf.sf); + break; } if (n >= len) From patchwork Thu Sep 17 08:17:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1365967 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.a=rsa-sha256 header.s=n1 header.b=UMurPvPM; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BsVN45Z51z9sRf for ; Thu, 17 Sep 2020 18:23:16 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726399AbgIQIXJ (ORCPT ); Thu, 17 Sep 2020 04:23:09 -0400 Received: from hqnvemgate26.nvidia.com ([216.228.121.65]:1408 "EHLO hqnvemgate26.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726342AbgIQIW5 (ORCPT ); Thu, 17 Sep 2020 04:22:57 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate26.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 01:17:35 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 01:17:48 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 01:17:48 -0700 Received: from sw-mtx-036.mtx.labs.mlnx (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 17 Sep 2020 08:17:47 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next 2/8] devlink: Support add and delete devlink port Date: Thu, 17 Sep 2020 11:17:25 +0300 Message-ID: <20200917081731.8363-3-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917081731.8363-1-parav@nvidia.com> References: <20200917081731.8363-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL101.nvidia.com (172.20.187.10) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600330655; bh=8+IeAygN8LQfvxyOMQi39R0WowkWFUAU/fgHn5VcrpU=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding: Content-Type:X-Originating-IP:X-ClientProxiedBy; b=UMurPvPM3YsFtrDOy/A/agyqN8jBLQrTesolyMp308WwV7oFMElVeNfxaJzgNWhvR xgiMg3jfumhhTkpK4FL+aLBxU62Jr4+MbPZ3i5vANccVYJ/UXTdkoWfHCeo74HAdXu wL1A/WXmX4wGtA3dz7aSwSM1afesKGbVa/YUjcU65yUgAFWwsNqZk8pSYGRhE8+yRV /5bAGs4Bq53C2i51wHmlbTyEsKD1SulPknZ/9uqPIWsxYGYKQBwE6eeLNXHUqFERsM jT23qjriC4exWe2kndZ4+SFmpFilkF1baP+ORJdOIEsx5AK9nrnMFPqmTyLSYZcf7L 87Y756Zj/7New== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Extended devlink interface for the user to add and delete port. Extend devlink to connect user requests to driver to add/delete such port in the device. When driver routines are invoked, devlink instance lock is not held. This enables driver to perform several devlink objects registration, unregistration such as (port, health reporter, resource etc) by using exising devlink APIs. This also helps to uniformly used the code for port registration during driver unload and during port deletion initiated by user. Examples of add, show and delete commands: Create a device with ID=10 and one physical port. $ echo "10 1" > /sys/bus/netdevsim/new_device $ devlink port show netdevsim/netdevsim10/0 netdevsim/netdevsim10/0: type eth netdev eni10np1 flavour physical port 1 splittable false $ devlink port add netdevsim/netdevsim10 flavour pcipf pfnum 0 $ devlink port show netdevsim/netdevsim10/1 netdevsim/netdevsim10/1: type eth netdev eni10npf0 flavour pcipf controller 0 pfnum 0 external false splittable false function: hw_addr 00:00:00:00:00:00 state inactive $ devlink port show netdevsim/netdevsim10/1 -jp { "port": { "netdevsim/netdevsim10/1": { "type": "eth", "netdev": "eni10npf0", "flavour": "pcipf", "controller": 0, "pfnum": 0, "external": false, "splittable": false, "function": { "hw_addr": "00:00:00:00:00:00", "state": "inactive" } } } } $ devlink port del netdevsim/netdevsim10/1 Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko --- include/net/devlink.h | 38 ++++++++++++++++++++++++ net/core/devlink.c | 67 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/include/net/devlink.h b/include/net/devlink.h index 1edb558125b0..ebab2c0360d0 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -142,6 +142,17 @@ struct devlink_port { struct mutex reporters_lock; /* Protects reporter_list */ }; +struct devlink_port_new_attrs { + enum devlink_port_flavour flavour; + unsigned int port_index; + u32 controller; + u32 sfnum; + u16 pfnum; + u8 port_index_valid:1, + controller_valid:1, + sfnum_valid:1; +}; + struct devlink_sb_pool_info { enum devlink_sb_pool_type pool_type; u32 size; @@ -1189,6 +1200,33 @@ struct devlink_ops { int (*port_function_hw_addr_set)(struct devlink *devlink, struct devlink_port *port, const u8 *hw_addr, int hw_addr_len, struct netlink_ext_ack *extack); + /** + * @port_new: Port add function. + * + * Should be used by device driver to let caller add new port of a specified flavour + * with optional attributes. + * Driver should return -EOPNOTSUPP if it doesn't support port addition of a specified + * flavour or specified attributes. Driver should set extack error message in case of fail + * to add the port. + * devlink core does not hold a devlink instance lock when this callback is invoked. + * Driver must ensures synchronization when adding or deleting a port. Driver must + * register a port with devlink core. + */ + int (*port_new)(struct devlink *devlink, const struct devlink_port_new_attrs *attrs, + struct netlink_ext_ack *extack); + /** + * @port_del: Port delete function. + * + * Should be used by device driver to let caller delete port which was previously created + * using port_new() callback. + * Driver should return -EOPNOTSUPP if it doesn't support port deletion. + * Driver should set extack error message in case of fail to delete the port. + * devlink core does not hold a devlink instance lock when this callback is invoked. + * Driver must ensures synchronization when adding or deleting a port. Driver must + * register a port with devlink core. + */ + int (*port_del)(struct devlink *devlink, unsigned int port_index, + struct netlink_ext_ack *extack); }; static inline void *devlink_priv(struct devlink *devlink) diff --git a/net/core/devlink.c b/net/core/devlink.c index fada660fd515..e93730065c57 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -991,6 +991,57 @@ static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, return devlink_port_unsplit(devlink, port_index, info->extack); } +static int devlink_nl_cmd_port_new_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct netlink_ext_ack *extack = info->extack; + struct devlink_port_new_attrs new_attrs = {}; + struct devlink *devlink = info->user_ptr[0]; + + if (!info->attrs[DEVLINK_ATTR_PORT_FLAVOUR] || + !info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]) { + NL_SET_ERR_MSG_MOD(extack, "Port flavour or PCI PF are not specified"); + return -EINVAL; + } + new_attrs.flavour = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_FLAVOUR]); + new_attrs.pfnum = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]); + + if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) { + new_attrs.port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); + new_attrs.port_index_valid = true; + } + if (info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]) { + new_attrs.controller = + nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]); + new_attrs.controller_valid = true; + } + if (info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]) { + new_attrs.sfnum = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]); + new_attrs.sfnum_valid = true; + } + + if (!devlink->ops->port_new) + return -EOPNOTSUPP; + + return devlink->ops->port_new(devlink, &new_attrs, extack); +} + +static int devlink_nl_cmd_port_del_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct netlink_ext_ack *extack = info->extack; + struct devlink *devlink = info->user_ptr[0]; + unsigned int port_index; + + if (!info->attrs[DEVLINK_ATTR_PORT_INDEX]) { + NL_SET_ERR_MSG_MOD(extack, "Port index is not specified"); + return -EINVAL; + } + port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); + + if (!devlink->ops->port_del) + return -EOPNOTSUPP; + return devlink->ops->port_del(devlink, port_index, extack); +} + static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, struct devlink_sb *devlink_sb, enum devlink_command cmd, u32 portid, @@ -7078,6 +7129,10 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 }, [DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 }, [DEVLINK_ATTR_PORT_FUNCTION] = { .type = NLA_NESTED }, + [DEVLINK_ATTR_PORT_FLAVOUR] = { .type = NLA_U16 }, + [DEVLINK_ATTR_PORT_PCI_PF_NUMBER] = { .type = NLA_U16 }, + [DEVLINK_ATTR_PORT_PCI_SF_NUMBER] = { .type = NLA_U32 }, + [DEVLINK_ATTR_PORT_CONTROLLER_NUMBER] = { .type = NLA_U32 }, }; static const struct genl_ops devlink_nl_ops[] = { @@ -7117,6 +7172,18 @@ static const struct genl_ops devlink_nl_ops[] = { .flags = GENL_ADMIN_PERM, .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, }, + { + .cmd = DEVLINK_CMD_PORT_NEW, + .doit = devlink_nl_cmd_port_new_doit, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, + }, + { + .cmd = DEVLINK_CMD_PORT_DEL, + .doit = devlink_nl_cmd_port_del_doit, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, + }, { .cmd = DEVLINK_CMD_SB_GET, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, From patchwork Thu Sep 17 08:17:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1365964 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.a=rsa-sha256 header.s=n1 header.b=H1kXQdti; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BsVMq5sWbz9sRf for ; Thu, 17 Sep 2020 18:23:03 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726379AbgIQIXB (ORCPT ); Thu, 17 Sep 2020 04:23:01 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:1664 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726348AbgIQIW5 (ORCPT ); Thu, 17 Sep 2020 04:22:57 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 01:17:06 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 01:17:49 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 01:17:49 -0700 Received: from sw-mtx-036.mtx.labs.mlnx (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 17 Sep 2020 08:17:48 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next 3/8] devlink: Prepare code to fill multiple port function attributes Date: Thu, 17 Sep 2020 11:17:26 +0300 Message-ID: <20200917081731.8363-4-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917081731.8363-1-parav@nvidia.com> References: <20200917081731.8363-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL101.nvidia.com (172.20.187.10) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600330626; bh=wdfLzZOZMJtp/ZqF6MO+GBRLjYMAiW+DHTHVJy6JAqI=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding: Content-Type:X-Originating-IP:X-ClientProxiedBy; b=H1kXQdtiZIq0MXs+gpyFwb5EK/UgGWSIr/yFx5j2bdYer7eZX336VVfb2j+/uHbyA ldmbqF3PDV+muYvm48OUof7siEeHb2kmVvGN044FO7saoSCAO7TT/B3MWJhhTjtdSE ItDIw8AoBMxlYf4wGz6gxJ+xL//JR8JLAfJXmx7cSroBmPbXW7eIGBg9Usq+8ek05q E/Odi4iqJqmtlsNYn+QxRb9FHdE13mifffArVY3RXRxX4TQz1J4kyOdUb8YO0yeQV1 41Nz4AYgFG6NnX9rm7qsi4IGQI9wnsciRk5HfSbA9tFIEJkT16heXAytJsP/JJ0f80 P1T/AzwNpGy0g== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Prepare code to fill zero or more port function optional attributes. Subsequent patch makes use of this to fill more port function attributes. Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko --- net/core/devlink.c | 53 +++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index e93730065c57..d152489e48da 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -570,6 +570,31 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg, return 0; } +static int +devlink_port_function_hw_addr_fill(struct devlink *devlink, const struct devlink_ops *ops, + struct devlink_port *port, struct sk_buff *msg, + struct netlink_ext_ack *extack, bool *msg_updated) +{ + u8 hw_addr[MAX_ADDR_LEN]; + int hw_addr_len; + int err; + + if (!ops->port_function_hw_addr_get) + return 0; + + err = ops->port_function_hw_addr_get(devlink, port, hw_addr, &hw_addr_len, extack); + if (err) { + if (err == -EOPNOTSUPP) + return 0; + return err; + } + err = nla_put(msg, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, hw_addr_len, hw_addr); + if (err) + return err; + *msg_updated = true; + return 0; +} + static int devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *port, struct netlink_ext_ack *extack) @@ -577,36 +602,16 @@ devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *por struct devlink *devlink = port->devlink; const struct devlink_ops *ops; struct nlattr *function_attr; - bool empty_nest = true; - int err = 0; + bool msg_updated = false; + int err; function_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PORT_FUNCTION); if (!function_attr) return -EMSGSIZE; ops = devlink->ops; - if (ops->port_function_hw_addr_get) { - int hw_addr_len; - u8 hw_addr[MAX_ADDR_LEN]; - - err = ops->port_function_hw_addr_get(devlink, port, hw_addr, &hw_addr_len, extack); - if (err == -EOPNOTSUPP) { - /* Port function attributes are optional for a port. If port doesn't - * support function attribute, returning -EOPNOTSUPP is not an error. - */ - err = 0; - goto out; - } else if (err) { - goto out; - } - err = nla_put(msg, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, hw_addr_len, hw_addr); - if (err) - goto out; - empty_nest = false; - } - -out: - if (err || empty_nest) + err = devlink_port_function_hw_addr_fill(devlink, ops, port, msg, extack, &msg_updated); + if (err || !msg_updated) nla_nest_cancel(msg, function_attr); else nla_nest_end(msg, function_attr); From patchwork Thu Sep 17 08:17:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1365968 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.a=rsa-sha256 header.s=n1 header.b=f1ZLKHRC; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BsVN91Zbcz9sRf for ; Thu, 17 Sep 2020 18:23:21 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726402AbgIQIXR (ORCPT ); Thu, 17 Sep 2020 04:23:17 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:3198 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726321AbgIQIW5 (ORCPT ); Thu, 17 Sep 2020 04:22:57 -0400 Received: from hqpgpgate102.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 01:16:21 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate102.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 01:17:49 -0700 X-PGP-Universal: processed; by hqpgpgate102.nvidia.com on Thu, 17 Sep 2020 01:17:49 -0700 Received: from sw-mtx-036.mtx.labs.mlnx (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 17 Sep 2020 08:17:49 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next 4/8] devlink: Support get and set state of port function Date: Thu, 17 Sep 2020 11:17:27 +0300 Message-ID: <20200917081731.8363-5-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917081731.8363-1-parav@nvidia.com> References: <20200917081731.8363-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL101.nvidia.com (172.20.187.10) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600330581; bh=wVUPQlv106oY+JsL8GVyqHIX8yKor1zTAaU/FqVuZ3A=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding: Content-Type:X-Originating-IP:X-ClientProxiedBy; b=f1ZLKHRC1MfWG+hk8DK8U+cc2kxnwY2IUengEn0vHDGn3fmjjWmCT0leQzkqe6hpr NqrVpdkVZCDAWg3qvxs86uvy2vO0VhUF/G8d563uxfHTx5sHBSHBv6aSQZ1kG3sUOm Mn2yJy8guhsrrtgJviQEJz+Ia8LqlH24K0bNWVCl9nchjjbMDi7nb0t9heJNHirNpo K9UofXAjgwFZA1RkDGyX5hkskZk5AoVzKHafrm1OKDFZmPi21Lm6l+VETzEGx+teqI +5iSeNJWJ43lec9P5CwQT0mAAp56XtV4XiF5CvgxbPJv1VM0QWleNYBSCZo5prKPMz E97HXc+/oP+nA== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org devlink port function can be in active or inactive state. Allow users to get and set port function's state. Example of a PCI SF port which supports a port function: Create a device with ID=10 and one physical port. $ echo "10 1" > /sys/bus/netdevsim/new_device $ devlink port show netdevsim/netdevsim10/0: type eth netdev eni10np1 flavour physical port 1 splittable false $ devlink port add netdevsim/netdevsim10/10 flavour pcipf pfnum 0 $ devlink port add netdevsim/netdevsim10/11 flavour pcisf pfnum 0 sfnum 44 $ devlink port show netdevsim/netdevsim10/11 netdevsim/netdevsim10/11: type eth netdev eni10npf0sf44 flavour pcisf controller 0 pfnum 0 sfnum 44 external false splittable false function: hw_addr 00:00:00:00:00:00 state inactive $ devlink port function set netdevsim/netdevsim10/11 hw_addr 00:11:22:33:44:55 state active $ devlink port show netdevsim/netdevsim10/11 -jp { "port": { "netdevsim/netdevsim10/11": { "type": "eth", "netdev": "eni10npf0sf44", "flavour": "pcisf", "controller": 0, "pfnum": 0, "sfnum": 44, "external": false, "splittable": false, "function": { "hw_addr": "00:11:22:33:44:55", "state": "active" } } } } Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko --- include/net/devlink.h | 20 ++++++++++ include/uapi/linux/devlink.h | 6 +++ net/core/devlink.c | 77 +++++++++++++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/include/net/devlink.h b/include/net/devlink.h index ebab2c0360d0..500c22835686 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -1200,6 +1200,26 @@ struct devlink_ops { int (*port_function_hw_addr_set)(struct devlink *devlink, struct devlink_port *port, const u8 *hw_addr, int hw_addr_len, struct netlink_ext_ack *extack); + /** + * @port_function_state_get: Port function's state get function. + * + * Should be used by device drivers to report the state of a function managed + * by the devlink port. Driver should return -EOPNOTSUPP if it doesn't support port + * function handling for a particular port. + */ + int (*port_function_state_get)(struct devlink *devlink, struct devlink_port *port, + enum devlink_port_function_state *state, + struct netlink_ext_ack *extack); + /** + * @port_function_state_set: Port function's state set function. + * + * Should be used by device drivers to set the state of a function managed + * by the devlink port. Driver should return -EOPNOTSUPP if it doesn't support port + * function handling for a particular port. + */ + int (*port_function_state_set)(struct devlink *devlink, struct devlink_port *port, + enum devlink_port_function_state state, + struct netlink_ext_ack *extack); /** * @port_new: Port add function. * diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index 09c41b9ce407..8e513f1cd638 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -518,9 +518,15 @@ enum devlink_resource_unit { enum devlink_port_function_attr { DEVLINK_PORT_FUNCTION_ATTR_UNSPEC, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, /* binary */ + DEVLINK_PORT_FUNCTION_ATTR_STATE, /* u8 */ __DEVLINK_PORT_FUNCTION_ATTR_MAX, DEVLINK_PORT_FUNCTION_ATTR_MAX = __DEVLINK_PORT_FUNCTION_ATTR_MAX - 1 }; +enum devlink_port_function_state { + DEVLINK_PORT_FUNCTION_STATE_INACTIVE, + DEVLINK_PORT_FUNCTION_STATE_ACTIVE, +}; + #endif /* _UAPI_LINUX_DEVLINK_H_ */ diff --git a/net/core/devlink.c b/net/core/devlink.c index d152489e48da..c82098cb75da 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -87,6 +87,9 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr); static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = { [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY }, + [DEVLINK_PORT_FUNCTION_ATTR_STATE] = + NLA_POLICY_RANGE(NLA_U8, DEVLINK_PORT_FUNCTION_STATE_INACTIVE, + DEVLINK_PORT_FUNCTION_STATE_ACTIVE), }; static LIST_HEAD(devlink_list); @@ -595,6 +598,40 @@ devlink_port_function_hw_addr_fill(struct devlink *devlink, const struct devlink return 0; } +static bool devlink_port_function_state_valid(u8 state) +{ + return state == DEVLINK_PORT_FUNCTION_STATE_INACTIVE || + state == DEVLINK_PORT_FUNCTION_STATE_ACTIVE; +} + +static int devlink_port_function_state_fill(struct devlink *devlink, const struct devlink_ops *ops, + struct devlink_port *port, struct sk_buff *msg, + struct netlink_ext_ack *extack, bool *msg_updated) +{ + enum devlink_port_function_state state; + int err; + + if (!ops->port_function_state_get) + return 0; + + err = ops->port_function_state_get(devlink, port, &state, extack); + if (err) { + if (err == -EOPNOTSUPP) + return 0; + return err; + } + if (!devlink_port_function_state_valid(state)) { + WARN_ON(1); + NL_SET_ERR_MSG_MOD(extack, "Invalid state value read from driver"); + return -EINVAL; + } + err = nla_put_u8(msg, DEVLINK_PORT_FUNCTION_ATTR_STATE, state); + if (err) + return err; + *msg_updated = true; + return 0; +} + static int devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *port, struct netlink_ext_ack *extack) @@ -611,6 +648,11 @@ devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *por ops = devlink->ops; err = devlink_port_function_hw_addr_fill(devlink, ops, port, msg, extack, &msg_updated); + if (err) + goto out; + err = devlink_port_function_state_fill(devlink, ops, port, msg, extack, &msg_updated); + +out: if (err || !msg_updated) nla_nest_cancel(msg, function_attr); else @@ -879,6 +921,28 @@ devlink_port_function_hw_addr_set(struct devlink *devlink, struct devlink_port * return 0; } +static int +devlink_port_function_state_set(struct devlink *devlink, struct devlink_port *port, + const struct nlattr *attr, struct netlink_ext_ack *extack) +{ + enum devlink_port_function_state state; + const struct devlink_ops *ops; + int err; + + state = nla_get_u8(attr); + ops = devlink->ops; + if (!ops->port_function_state_set) { + NL_SET_ERR_MSG_MOD(extack, "Port function does not support state setting"); + return -EOPNOTSUPP; + } + err = ops->port_function_state_set(devlink, port, state, extack); + if (err) + return err; + + devlink_port_notify(port, DEVLINK_CMD_PORT_NEW); + return 0; +} + static int devlink_port_function_set(struct devlink *devlink, struct devlink_port *port, const struct nlattr *attr, struct netlink_ext_ack *extack) @@ -894,9 +958,18 @@ devlink_port_function_set(struct devlink *devlink, struct devlink_port *port, } attr = tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]; - if (attr) + if (attr) { err = devlink_port_function_hw_addr_set(devlink, port, attr, extack); - + if (err) + return err; + } + /* Keep this as the last function attribute set, so that when + * multiple port function attributes are set along with state, + * Those can be applied first before activating the state. + */ + attr = tb[DEVLINK_PORT_FUNCTION_ATTR_STATE]; + if (attr) + err = devlink_port_function_state_set(devlink, port, attr, extack); return err; } From patchwork Thu Sep 17 08:17:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1365969 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.a=rsa-sha256 header.s=n1 header.b=YTU/sSjU; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BsVNQ3WqGz9sRf for ; Thu, 17 Sep 2020 18:23:34 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726403AbgIQIXY (ORCPT ); Thu, 17 Sep 2020 04:23:24 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:3200 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726340AbgIQIW7 (ORCPT ); Thu, 17 Sep 2020 04:22:59 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 01:16:22 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 01:17:50 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 01:17:50 -0700 Received: from sw-mtx-036.mtx.labs.mlnx (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 17 Sep 2020 08:17:49 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next 5/8] netdevsim: Add support for add and delete of a PCI PF port Date: Thu, 17 Sep 2020 11:17:28 +0300 Message-ID: <20200917081731.8363-6-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917081731.8363-1-parav@nvidia.com> References: <20200917081731.8363-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL101.nvidia.com (172.20.187.10) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600330582; bh=k0NjwRB4Z8bkUU37kbMjeYgHFICT0SXOf49kNsvYOkw=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding: Content-Type:X-Originating-IP:X-ClientProxiedBy; b=YTU/sSjUPYu0RQVIcpEBXp2AwKms5mPcoPNbvHJOHmfpb1YadH/6vzND4CQMpyDdZ wo66EH8rUVl8mat74W7LggK7ArSkJ6+RvUM60o20PwIIAltPn3+Wj4IPGsHHvQsmeq v7i/4JKJdfaLcES51hI1TekWOK8X4ZlY+tM5f00idjEwxoIpxl3nXLYHYCH5pa0M0B 7XHQjklXLxBrI6tVLsnPjK30DxpGcocycqgzfJQeMvxGFiXQ7BEBfTQe8vVe0bfkQU lpBJqnIXU5b7dnDnOrZDpa4WAIUMGtrIShljHAbXIzVsCtMbgmgBuCchk9kS5zdkXF SHRD/JmoLZLQA== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Simulate PCI PF ports. Allow user to create one or more PCI PF ports. Examples: Create a device with ID=10 and one physical port. $ echo "10 1" > /sys/bus/netdevsim/new_device $ devlink port show netdevsim/netdevsim10/0: type eth netdev eni10np1 flavour physical port 1 splittable false Add and show devlink port of flavour 'pcipf' for PF number 0. $ devlink port add netdevsim/netdevsim10/10 flavour pcipf pfnum 0 $ devlink port show netdevsim/netdevsim10/10 netdevsim/netdevsim10/10: type eth netdev eni10npf0 flavour pcipf controller 0 pfnum 0 external false splittable false function: hw_addr 00:00:00:00:00:00 state inactive Delete newly added devlink port $ devlink port add netdevsim/netdevsim10/10 Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko --- drivers/net/netdevsim/Makefile | 3 +- drivers/net/netdevsim/dev.c | 10 + drivers/net/netdevsim/netdevsim.h | 19 ++ drivers/net/netdevsim/port_function.c | 337 ++++++++++++++++++++++++++ 4 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 drivers/net/netdevsim/port_function.c diff --git a/drivers/net/netdevsim/Makefile b/drivers/net/netdevsim/Makefile index ade086eed955..e69e895af62c 100644 --- a/drivers/net/netdevsim/Makefile +++ b/drivers/net/netdevsim/Makefile @@ -3,7 +3,8 @@ obj-$(CONFIG_NETDEVSIM) += netdevsim.o netdevsim-objs := \ - netdev.o dev.o ethtool.o fib.o bus.o health.o udp_tunnels.o + netdev.o dev.o ethtool.o fib.o bus.o health.o udp_tunnels.o \ + port_function.o ifeq ($(CONFIG_BPF_SYSCALL),y) netdevsim-objs += \ diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 32f339fedb21..e3b81c8b5125 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -884,6 +884,8 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .trap_group_set = nsim_dev_devlink_trap_group_set, .trap_policer_set = nsim_dev_devlink_trap_policer_set, .trap_policer_counter_get = nsim_dev_devlink_trap_policer_counter_get, + .port_new = nsim_dev_devlink_port_new, + .port_del = nsim_dev_devlink_port_del, }; #define NSIM_DEV_MAX_MACS_DEFAULT 32 @@ -1017,6 +1019,8 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev, nsim_dev->ddir, nsim_dev, &nsim_dev_take_snapshot_fops); + + nsim_dev_port_function_enable(nsim_dev); return 0; err_health_exit: @@ -1050,6 +1054,7 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT; nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT; spin_lock_init(&nsim_dev->fa_cookie_lock); + nsim_dev_port_function_init(nsim_dev); dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev); @@ -1097,6 +1102,7 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) if (err) goto err_bpf_dev_exit; + nsim_dev_port_function_enable(nsim_dev); devlink_params_publish(devlink); devlink_reload_enable(devlink); return 0; @@ -1131,6 +1137,9 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev) if (devlink_is_reload_failed(devlink)) return; + + /* Disable and destroy any user created devlink ports */ + nsim_dev_port_function_disable(nsim_dev); debugfs_remove(nsim_dev->take_snapshot); nsim_dev_port_del_all(nsim_dev); nsim_dev_health_exit(nsim_dev); @@ -1155,6 +1164,7 @@ void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev) ARRAY_SIZE(nsim_devlink_params)); devlink_unregister(devlink); devlink_resources_unregister(devlink, NULL); + nsim_dev_port_function_exit(nsim_dev); devlink_free(devlink); } diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 0c86561e6d8d..aec3c4d5fda7 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -213,6 +213,16 @@ struct nsim_dev { bool ipv4_only; u32 sleep; } udp_ports; + struct { + refcount_t refcount; /* refcount along with disable_complete serializes + * port operations with port function disablement + * during driver unload. + */ + struct completion disable_complete; + struct list_head head; + struct ida ida; + struct ida pfnum_ida; + } port_functions; }; static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev) @@ -283,3 +293,12 @@ struct nsim_bus_dev { int nsim_bus_init(void); void nsim_bus_exit(void); + +void nsim_dev_port_function_init(struct nsim_dev *nsim_dev); +void nsim_dev_port_function_exit(struct nsim_dev *nsim_dev); +void nsim_dev_port_function_enable(struct nsim_dev *nsim_dev); +void nsim_dev_port_function_disable(struct nsim_dev *nsim_dev); +int nsim_dev_devlink_port_new(struct devlink *devlink, const struct devlink_port_new_attrs *attrs, + struct netlink_ext_ack *extack); +int nsim_dev_devlink_port_del(struct devlink *devlink, unsigned int port_index, + struct netlink_ext_ack *extack); diff --git a/drivers/net/netdevsim/port_function.c b/drivers/net/netdevsim/port_function.c new file mode 100644 index 000000000000..9a1634898c7d --- /dev/null +++ b/drivers/net/netdevsim/port_function.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* Copyright (c) 2020 Mellanox Technologies Ltd. */ + +#include +#include + +#include "netdevsim.h" + +struct nsim_port_function { + struct devlink_port dl_port; + struct net_device *netdev; + struct list_head list; + unsigned int port_index; + enum devlink_port_flavour flavour; + u32 controller; + u16 pfnum; + struct nsim_port_function *pf_port; /* Valid only for SF port */ +}; + +void nsim_dev_port_function_init(struct nsim_dev *nsim_dev) +{ + refcount_set(&nsim_dev->port_functions.refcount, 0); + INIT_LIST_HEAD(&nsim_dev->port_functions.head); + ida_init(&nsim_dev->port_functions.ida); + ida_init(&nsim_dev->port_functions.pfnum_ida); +} + +void nsim_dev_port_function_exit(struct nsim_dev *nsim_dev) +{ + 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)); + ida_destroy(&nsim_dev->port_functions.ida); + WARN_ON(!list_empty(&nsim_dev->port_functions.head)); + WARN_ON(refcount_read(&nsim_dev->port_functions.refcount)); +} + +static bool nsim_dev_port_function_try_get(struct nsim_dev *nsim_dev) +{ + return refcount_inc_not_zero(&nsim_dev->port_functions.refcount); +} + +static void nsim_dev_port_function_put(struct nsim_dev *nsim_dev) +{ + if (refcount_dec_and_test(&nsim_dev->port_functions.refcount)) + complete(&nsim_dev->port_functions.disable_complete); +} + +static struct devlink_port *nsim_dev_port_function_get_devlink_port(struct net_device *dev) +{ + struct nsim_port_function *port = netdev_priv(dev); + + return &port->dl_port; +} + +static netdev_tx_t nsim_dev_port_function_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + dev_kfree_skb(skb); + return NETDEV_TX_OK; +} + +static const struct net_device_ops nsim_netdev_ops = { + .ndo_start_xmit = nsim_dev_port_function_start_xmit, + .ndo_get_devlink_port = nsim_dev_port_function_get_devlink_port, +}; + +static void nsim_port_function_ndev_setup(struct net_device *dev) +{ + ether_setup(dev); + eth_hw_addr_random(dev); + + dev->tx_queue_len = 0; + dev->flags |= IFF_NOARP; + dev->flags &= ~IFF_MULTICAST; + dev->max_mtu = ETH_MAX_MTU; +} + +static struct nsim_port_function * +nsim_devlink_port_function_alloc(struct nsim_dev *dev, const struct devlink_port_new_attrs *attrs) +{ + struct nsim_bus_dev *nsim_bus_dev = dev->nsim_bus_dev; + struct nsim_port_function *port; + struct net_device *netdev; + int ret; + + netdev = alloc_netdev(sizeof(*port), "eth%d", NET_NAME_UNKNOWN, + nsim_port_function_ndev_setup); + if (!netdev) + return ERR_PTR(-ENOMEM); + + dev_net_set(netdev, nsim_dev_net(dev)); + netdev->netdev_ops = &nsim_netdev_ops; + nsim_bus_dev = dev->nsim_bus_dev; + SET_NETDEV_DEV(netdev, &nsim_bus_dev->dev); + + port = netdev_priv(netdev); + memset(port, 0, sizeof(*port)); + port->netdev = netdev; + port->flavour = attrs->flavour; + + if (attrs->port_index_valid) + ret = ida_alloc_range(&dev->port_functions.ida, attrs->port_index, + attrs->port_index, GFP_KERNEL); + else + ret = ida_alloc_min(&dev->port_functions.ida, nsim_bus_dev->port_count, GFP_KERNEL); + if (ret < 0) + goto port_ida_err; + + port->port_index = ret; + port->controller = attrs->controller_valid ? attrs->controller : 0; + + switch (port->flavour) { + case DEVLINK_PORT_FLAVOUR_PCI_PF: + ret = ida_alloc_range(&dev->port_functions.pfnum_ida, attrs->pfnum, attrs->pfnum, + GFP_KERNEL); + if (ret < 0) + goto fn_ida_err; + port->pfnum = ret; + break; + default: + break; + }; + return port; + +fn_ida_err: + ida_simple_remove(&dev->port_functions.ida, port->port_index); +port_ida_err: + free_netdev(netdev); + return ERR_PTR(ret); +} + +static void nsim_devlink_port_function_free(struct nsim_dev *dev, struct nsim_port_function *port) +{ + switch (port->flavour) { + case DEVLINK_PORT_FLAVOUR_PCI_PF: + ida_simple_remove(&dev->port_functions.pfnum_ida, port->pfnum); + break; + default: + break; + }; + ida_simple_remove(&dev->port_functions.ida, port->port_index); + free_netdev(port->netdev); +} + +static bool nsim_dev_port_index_internal(struct nsim_dev *nsim_dev, unsigned int port_index) +{ + struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev; + + return (port_index < nsim_bus_dev->port_count) ? true : false; +} + +static bool +nsim_dev_port_port_exists(struct nsim_dev *nsim_dev, const struct devlink_port_new_attrs *attrs) +{ + struct nsim_port_function *tmp; + + list_for_each_entry(tmp, &nsim_dev->port_functions.head, list) { + if (attrs->port_index_valid && tmp->port_index == attrs->port_index) + return true; + if (attrs->controller_valid && tmp->controller != attrs->controller) + continue; + /* If controller is provided, and if the port is for a specific controller, + * skip them. + */ + if (!attrs->controller_valid && tmp->controller) + continue; + + if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF && + tmp->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF && tmp->pfnum == attrs->pfnum) + return true; + } + return false; +} + +static struct nsim_port_function * +nsim_dev_devlink_port_index_lookup(const struct nsim_dev *nsim_dev, unsigned int port_index, + struct netlink_ext_ack *extack) +{ + struct nsim_port_function *port; + + list_for_each_entry(port, &nsim_dev->port_functions.head, list) { + if (port->port_index != port_index) + continue; + return port; + } + NL_SET_ERR_MSG_MOD(extack, "User created port not found"); + return ERR_PTR(-ENOENT); +} + +static int nsim_devlink_port_function_add(struct devlink *devlink, struct nsim_dev *nsim_dev, + struct nsim_port_function *port, + struct netlink_ext_ack *extack) +{ + int err; + + list_add(&port->list, &nsim_dev->port_functions.head); + + err = devlink_port_register(devlink, &port->dl_port, port->port_index); + if (err) + goto reg_err; + + err = register_netdev(port->netdev); + if (err) + goto netdev_err; + + devlink_port_type_eth_set(&port->dl_port, port->netdev); + return 0; + +netdev_err: + devlink_port_type_clear(&port->dl_port); + devlink_port_unregister(&port->dl_port); +reg_err: + list_del(&port->list); + return err; +} + +static void nsim_devlink_port_function_del(struct nsim_dev *nsim_dev, + struct nsim_port_function *port) +{ + devlink_port_type_clear(&port->dl_port); + unregister_netdev(port->netdev); + devlink_port_unregister(&port->dl_port); + list_del(&port->list); +} + +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; +} + +int nsim_dev_devlink_port_new(struct devlink *devlink, const struct devlink_port_new_attrs *attrs, + struct netlink_ext_ack *extack) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + struct nsim_bus_dev *nsim_bus_dev; + struct nsim_port_function *port; + int err; + + nsim_bus_dev = nsim_dev->nsim_bus_dev; + if (attrs->port_index_valid && attrs->port_index < nsim_bus_dev->port_count) { + NL_SET_ERR_MSG_MOD(extack, "Port with given port index already exist"); + return -EEXIST; + } + if (!nsim_dev_port_flavour_supported(nsim_dev, attrs)) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported port flavour specified"); + return -EOPNOTSUPP; + } + if (!nsim_dev_port_function_try_get(nsim_dev)) + return -EPERM; + if (nsim_dev_port_port_exists(nsim_dev, attrs)) { + NL_SET_ERR_MSG_MOD(extack, "Port with given attributes already exists"); + err = -EEXIST; + goto alloc_err; + } + port = nsim_devlink_port_function_alloc(nsim_dev, attrs); + if (IS_ERR(port)) { + NL_SET_ERR_MSG_MOD(extack, "Fail to allocate port"); + err = PTR_ERR(port); + goto alloc_err; + } + memcpy(port->dl_port.attrs.switch_id.id, nsim_dev->switch_id.id, + 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, port->controller, port->pfnum, false); + + err = nsim_devlink_port_function_add(devlink, nsim_dev, port, extack); + if (err) + goto add_err; + + nsim_dev_port_function_put(nsim_dev); + return 0; + +add_err: + nsim_devlink_port_function_free(nsim_dev, port); +alloc_err: + nsim_dev_port_function_put(nsim_dev); + return err; +} + +int nsim_dev_devlink_port_del(struct devlink *devlink, unsigned int port_index, + struct netlink_ext_ack *extack) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + struct nsim_port_function *port; + + if (nsim_dev_port_index_internal(nsim_dev, port_index)) { + NL_SET_ERR_MSG_MOD(extack, "Port index doesn't belong to user created port"); + return -EINVAL; + } + + if (!nsim_dev_port_function_try_get(nsim_dev)) + return -EPERM; + + port = nsim_dev_devlink_port_index_lookup(nsim_dev, port_index, extack); + if (IS_ERR(port)) + goto err; + nsim_devlink_port_function_del(nsim_dev, port); + nsim_devlink_port_function_free(nsim_dev, port); + nsim_dev_port_function_put(nsim_dev); + return 0; + +err: + nsim_dev_port_function_put(nsim_dev); + return PTR_ERR(port); +} + +void nsim_dev_port_function_enable(struct nsim_dev *nsim_dev) +{ + init_completion(&nsim_dev->port_functions.disable_complete); + refcount_set(&nsim_dev->port_functions.refcount, 1); +} + +void nsim_dev_port_function_disable(struct nsim_dev *nsim_dev) +{ + struct nsim_port_function *port; + struct nsim_port_function *tmp; + + /* Balances with refcount_set(); drop the refcount so that + * any new port new/del or port function get/set commands + * cannot start. + */ + nsim_dev_port_function_put(nsim_dev); + /* Wait for any ongoing commands to complete. */ + wait_for_completion(&nsim_dev->port_functions.disable_complete); + + /* At this point, no new user commands can start and any ongoing + * commands have completed, so it is safe to delete all user created + * ports. + */ + + list_for_each_entry_safe_reverse(port, tmp, &nsim_dev->port_functions.head, list) { + nsim_devlink_port_function_del(nsim_dev, port); + nsim_devlink_port_function_free(nsim_dev, port); + } +} From patchwork Thu Sep 17 08:17:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1365970 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.a=rsa-sha256 header.s=n1 header.b=dB1KsLHG; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BsVNW49jlz9sRf for ; Thu, 17 Sep 2020 18:23:39 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726411AbgIQIXi (ORCPT ); Thu, 17 Sep 2020 04:23:38 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:3215 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726327AbgIQIXA (ORCPT ); Thu, 17 Sep 2020 04:23:00 -0400 Received: from hqpgpgate102.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 01:16:22 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate102.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 01:17:51 -0700 X-PGP-Universal: processed; by hqpgpgate102.nvidia.com on Thu, 17 Sep 2020 01:17:51 -0700 Received: from sw-mtx-036.mtx.labs.mlnx (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 17 Sep 2020 08:17:50 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next 6/8] netdevsim: Simulate get/set hardware address of a PCI port Date: Thu, 17 Sep 2020 11:17:29 +0300 Message-ID: <20200917081731.8363-7-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917081731.8363-1-parav@nvidia.com> References: <20200917081731.8363-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL101.nvidia.com (172.20.187.10) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600330582; bh=J1uudAjTs8OjBTm8K5WqPWaeWin6JwWh6TZlCPZlrr8=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding: Content-Type:X-Originating-IP:X-ClientProxiedBy; b=dB1KsLHGXV6x8h4SI2bgi12hrFq6RCDnggxClMdZALUGxcJx2t7XOCwyLqtmHW+0C FzazX1oQ21n3lS/nR6ake85+i5av5O7H/aHTDrs/fPuPoUwsDMrRQl2q5SuBQ/yrqy StyKkpnl9A7lWHAG5C/iNRtHgLPxeotenwCIsexdgib1uy92MlC7vlmtkI5fXoxxrj ONE6KnCoTiexMOyZzYm4s08X5UorPmQZf1Dk/v3eGdePRbE0bMiAqNjKyw7/HQQGor /Gw9GAcECHLls+Kv/Rgzg80SslF3WKoKAA0RYqbHPCSC7L4dM+1eBUyjWAkHQzoOv7 73OxORZg2fhag== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Allow users to get/set hardware address for the PCI port. Below example creates one devlink port, queries a port, sets a hardware address. Example of a PCI SF port which supports a port function hw_addr set: Create a device with ID=10 and one physical port. $ echo "10 1" > /sys/bus/netdevsim/new_device $ devlink port show netdevsim/netdevsim10/0: type eth netdev eni10np1 flavour physical port 1 splittable false $ devlink port add netdevsim/netdevsim10/10 flavour pcipf pfnum 0 $ devlink port show netdevsim/netdevsim10/10 netdevsim/netdevsim10/10: type eth netdev eni10npf0 flavour pcipf controller 0 pfnum 0 external false splittable false function: hw_addr 00:00:00:00:00:00 state inactive $ devlink port function set netdevsim/netdevsim10/10 hw_addr 00:11:22:33:44:55 $ devlink port show netdevsim/netdevsim10/10 -jp { "port": { "netdevsim/netdevsim10/11": { "type": "eth", "netdev": "eni10npf0", "flavour": "pcisf", "controller": 0, "pfnum": 0, "sfnum": 44, "external": true, "splittable": false, "function": { "hw_addr": "00:11:22:33:44:55" } } } } Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko --- drivers/net/netdevsim/dev.c | 2 ++ drivers/net/netdevsim/netdevsim.h | 6 ++++ drivers/net/netdevsim/port_function.c | 44 +++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index e3b81c8b5125..ef2e293f358b 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -886,6 +886,8 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .trap_policer_counter_get = nsim_dev_devlink_trap_policer_counter_get, .port_new = nsim_dev_devlink_port_new, .port_del = nsim_dev_devlink_port_del, + .port_function_hw_addr_get = nsim_dev_port_function_hw_addr_get, + .port_function_hw_addr_set = nsim_dev_port_function_hw_addr_set, }; #define NSIM_DEV_MAX_MACS_DEFAULT 32 diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index aec3c4d5fda7..8dc8f4e5dcd8 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -302,3 +302,9 @@ int nsim_dev_devlink_port_new(struct devlink *devlink, const struct devlink_port struct netlink_ext_ack *extack); int nsim_dev_devlink_port_del(struct devlink *devlink, unsigned int port_index, struct netlink_ext_ack *extack); +int nsim_dev_port_function_hw_addr_get(struct devlink *devlink, struct devlink_port *port, + u8 *hw_addr, int *hw_addr_len, + struct netlink_ext_ack *extack); +int nsim_dev_port_function_hw_addr_set(struct devlink *devlink, struct devlink_port *port, + const u8 *hw_addr, int hw_addr_len, + struct netlink_ext_ack *extack); diff --git a/drivers/net/netdevsim/port_function.c b/drivers/net/netdevsim/port_function.c index 9a1634898c7d..0053f6f6d530 100644 --- a/drivers/net/netdevsim/port_function.c +++ b/drivers/net/netdevsim/port_function.c @@ -15,6 +15,7 @@ struct nsim_port_function { u32 controller; u16 pfnum; struct nsim_port_function *pf_port; /* Valid only for SF port */ + u8 hw_addr[ETH_ALEN]; }; void nsim_dev_port_function_init(struct nsim_dev *nsim_dev) @@ -335,3 +336,46 @@ void nsim_dev_port_function_disable(struct nsim_dev *nsim_dev) nsim_devlink_port_function_free(nsim_dev, port); } } + +static struct nsim_port_function *nsim_dev_to_port_function(struct nsim_dev *nsim_dev, + struct devlink_port *dl_port) +{ + if (nsim_dev_port_index_internal(nsim_dev, dl_port->index)) + return ERR_PTR(-EOPNOTSUPP); + return container_of(dl_port, struct nsim_port_function, dl_port); +} + +int nsim_dev_port_function_hw_addr_get(struct devlink *devlink, struct devlink_port *dl_port, + u8 *hw_addr, int *hw_addr_len, + struct netlink_ext_ack *extack) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + struct nsim_port_function *port; + + port = nsim_dev_to_port_function(nsim_dev, dl_port); + if (IS_ERR(port)) + return PTR_ERR(port); + + memcpy(hw_addr, port->hw_addr, ETH_ALEN); + *hw_addr_len = ETH_ALEN; + return 0; +} + +int nsim_dev_port_function_hw_addr_set(struct devlink *devlink, struct devlink_port *dl_port, + const u8 *hw_addr, int hw_addr_len, + struct netlink_ext_ack *extack) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + struct nsim_port_function *port; + + if (hw_addr_len != ETH_ALEN) { + NL_SET_ERR_MSG_MOD(extack, "Hardware address must be 6 bytes long"); + return -EOPNOTSUPP; + } + port = nsim_dev_to_port_function(nsim_dev, dl_port); + if (IS_ERR(port)) + return PTR_ERR(port); + + memcpy(port->hw_addr, hw_addr, ETH_ALEN); + return 0; +} From patchwork Thu Sep 17 08:17:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1365971 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.a=rsa-sha256 header.s=n1 header.b=C7ZxqFrX; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BsVNZ45mqz9sRf for ; Thu, 17 Sep 2020 18:23:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726419AbgIQIXj (ORCPT ); Thu, 17 Sep 2020 04:23:39 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:3216 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726336AbgIQIXA (ORCPT ); Thu, 17 Sep 2020 04:23:00 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 01:16:23 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 01:17:51 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 01:17:51 -0700 Received: from sw-mtx-036.mtx.labs.mlnx (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 17 Sep 2020 08:17:51 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next 7/8] netdevsim: Simulate port function state for a PCI port Date: Thu, 17 Sep 2020 11:17:30 +0300 Message-ID: <20200917081731.8363-8-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917081731.8363-1-parav@nvidia.com> References: <20200917081731.8363-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL101.nvidia.com (172.20.187.10) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600330583; bh=dlgf/hzHFUU01/jz4HU/G8eDcuKhu9EucPHJsZhzOqY=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding: Content-Type:X-Originating-IP:X-ClientProxiedBy; b=C7ZxqFrXES0dRkKKALfvT/OQKYSYmLP2r9rmmIg1ic9BzAYy9G5EEVyae8mPK2gQh eyglcNdHxCg2auwAaO+FAwdRkk5uFvtjoRB0l2A1L1Np8IiRqbvtrWTsEU5/UjpQqk r7dZ4/kJTIs6woi6lzV9tlIUoGFnPOb0Qp5Crhjw8VhWr83GzE9wn0qOwtSVJ72MWc kaO/OtnUAKYMpNW9b+XvFaYdjD/ImMuSZFOlTSpMU2bOCXqUSMhFCop9ndl5P4qSC4 eJE0kb35kzY7fTrTCUMZgStbo7czdy+ejM9F5TtFoOPoSsKOhRs8WRoyv6yKCoE+Y+ 11IdSEsrz4wsg== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Simulate port function state of a PCI port. This enables users to get and set the state of the PCI port function. Example of a PCI SF port which supports a port function: Create a device with ID=10 and one physical port. $ echo "10 1" > /sys/bus/netdevsim/new_device $ devlink port show netdevsim/netdevsim10/0: type eth netdev eni10np1 flavour physical port 1 splittable false $ devlink port add netdevsim/netdevsim10/10 flavour pcipf pfnum 0 $ devlink port function set netdevsim/netdevsim10/10 hw_addr 00:11:22:33:44:55 state active $ devlink port show netdevsim/netdevsim10/10 netdevsim/netdevsim10/10: type eth netdev eni10npf0 flavour pcipf controller 0 pfnum 0 external true splittable false function: hw_addr 00:00:00:00:00:00 state inactive $ devlink port function set netdevsim/netdevsim10/10 hw_addr 00:11:22:33:44:55 state active $ devlink port show netdevsim/netdevsim10/10 -jp { "port": { "netdevsim/netdevsim10/10": { "type": "eth", "netdev": "eni10npf0", "flavour": "pcipf", "controller": 0, "pfnum": 0, "external": false, "splittable": false, "function": { "hw_addr": "00:11:22:33:44:55", "state": "active" } } } } Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko --- drivers/net/netdevsim/dev.c | 2 ++ drivers/net/netdevsim/netdevsim.h | 6 ++++++ drivers/net/netdevsim/port_function.c | 30 +++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index ef2e293f358b..ec1e5dc74be1 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -888,6 +888,8 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .port_del = nsim_dev_devlink_port_del, .port_function_hw_addr_get = nsim_dev_port_function_hw_addr_get, .port_function_hw_addr_set = nsim_dev_port_function_hw_addr_set, + .port_function_state_get = nsim_dev_port_function_state_get, + .port_function_state_set = nsim_dev_port_function_state_set, }; #define NSIM_DEV_MAX_MACS_DEFAULT 32 diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 8dc8f4e5dcd8..0ea9705eda38 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -308,3 +308,9 @@ int nsim_dev_port_function_hw_addr_get(struct devlink *devlink, struct devlink_p int nsim_dev_port_function_hw_addr_set(struct devlink *devlink, struct devlink_port *port, const u8 *hw_addr, int hw_addr_len, struct netlink_ext_ack *extack); +int nsim_dev_port_function_state_get(struct devlink *devlink, struct devlink_port *port, + enum devlink_port_function_state *state, + struct netlink_ext_ack *extack); +int nsim_dev_port_function_state_set(struct devlink *devlink, struct devlink_port *port, + enum devlink_port_function_state state, + struct netlink_ext_ack *extack); diff --git a/drivers/net/netdevsim/port_function.c b/drivers/net/netdevsim/port_function.c index 0053f6f6d530..01587b54f0e0 100644 --- a/drivers/net/netdevsim/port_function.c +++ b/drivers/net/netdevsim/port_function.c @@ -16,6 +16,7 @@ struct nsim_port_function { u16 pfnum; struct nsim_port_function *pf_port; /* Valid only for SF port */ u8 hw_addr[ETH_ALEN]; + u8 state; /* enum devlink_port_function_state */ }; void nsim_dev_port_function_init(struct nsim_dev *nsim_dev) @@ -196,6 +197,7 @@ static int nsim_devlink_port_function_add(struct devlink *devlink, struct nsim_d list_add(&port->list, &nsim_dev->port_functions.head); + port->state = DEVLINK_PORT_FUNCTION_STATE_INACTIVE; err = devlink_port_register(devlink, &port->dl_port, port->port_index); if (err) goto reg_err; @@ -379,3 +381,31 @@ int nsim_dev_port_function_hw_addr_set(struct devlink *devlink, struct devlink_p memcpy(port->hw_addr, hw_addr, ETH_ALEN); return 0; } + +int nsim_dev_port_function_state_get(struct devlink *devlink, struct devlink_port *dl_port, + enum devlink_port_function_state *state, + struct netlink_ext_ack *extack) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + struct nsim_port_function *port; + + port = nsim_dev_to_port_function(nsim_dev, dl_port); + if (IS_ERR(port)) + return PTR_ERR(port); + *state = port->state; + return 0; +} + +int nsim_dev_port_function_state_set(struct devlink *devlink, struct devlink_port *dl_port, + enum devlink_port_function_state state, + struct netlink_ext_ack *extack) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + struct nsim_port_function *port; + + port = nsim_dev_to_port_function(nsim_dev, dl_port); + if (IS_ERR(port)) + return PTR_ERR(port); + port->state = state; + return 0; +} From patchwork Thu Sep 17 08:17:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1365966 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.a=rsa-sha256 header.s=n1 header.b=QtOvFJio; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BsVMw5BPHz9sRf for ; Thu, 17 Sep 2020 18:23:08 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726392AbgIQIXH (ORCPT ); Thu, 17 Sep 2020 04:23:07 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:1676 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726350AbgIQIW5 (ORCPT ); Thu, 17 Sep 2020 04:22:57 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 01:17:09 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 01:17:52 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 01:17:52 -0700 Received: from sw-mtx-036.mtx.labs.mlnx (10.124.1.5) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 17 Sep 2020 08:17:51 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next 8/8] netdevsim: Add support for add and delete PCI SF port Date: Thu, 17 Sep 2020 11:17:31 +0300 Message-ID: <20200917081731.8363-9-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917081731.8363-1-parav@nvidia.com> References: <20200917081731.8363-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL101.nvidia.com (172.20.187.10) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600330629; bh=5XAO3Vw0TgtQm7gK0fSkjxFoCJnTlDYbpJN9T2fiODw=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding: Content-Type:X-Originating-IP:X-ClientProxiedBy; b=QtOvFJiocVQDEuurr5K7q4NgV/XzmV25s2obnoOJvmaTOTCIEKSZIn9jV51+EHpG+ U3WK8sKCIdpHBFLGiADOAxFY0RPuxag3806n1av6XLOlPLf+2GVPbOuWmVkCB/kUAp hOUSwWIfkaWLnL3me4/Nk8Bw8P631ZAj7GG3wlYDEpjmFwPd+VVdT0jmx4lDVsOzPI JTEe7l8Lb6ivAXW8dXitbhqzZHwcBXfsAVSQTXXJBjHEWvOpqtzpdA+TEHZVGmnLzj mTSfnk7Tlk17rGzMf02+vGxxrDdsRGLRhz8+EeOxOaj+wp+M+h37yLyfJDKnwRU4Rv 74gpNRFwAAgcw== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Simulate PCI SF ports. Allow user to create one or more PCI SF ports. Examples: Create a PCI PF and PCI SF port. Create a device with ID=10 and one physical port. $ echo "10 1" > /sys/bus/netdevsim/new_device $ devlink port show netdevsim/netdevsim10/0: type eth netdev eni10np1 flavour physical port 1 splittable false $ devlink port add netdevsim/netdevsim10/10 flavour pcipf pfnum 0 $ devlink port add netdevsim/netdevsim10/11 flavour pcisf pfnum 0 sfnum 44 $ devlink port show netdevsim/netdevsim10/11 netdevsim/netdevsim10/11: type eth netdev eni10npf0sf44 flavour pcisf controller 0 pfnum 0 sfnum 44 external true splittable false function: hw_addr 00:00:00:00:00:00 state inactive $ devlink port function set netdevsim/netdevsim10/11 hw_addr 00:11:22:33:44:55 state active $ devlink port show netdevsim/netdevsim10/11 -jp { "port": { "netdevsim/netdevsim10/11": { "type": "eth", "netdev": "eni10npf0sf44", "flavour": "pcisf", "controller": 0, "pfnum": 0, "sfnum": 44, "external": true, "splittable": false, "function": { "hw_addr": "00:11:22:33:44:55", "state": "active" } } } } Delete newly added devlink port $ devlink port add netdevsim/netdevsim10/11 Add devlink port of flavour 'pcisf' where port index and sfnum are auto assigned by driver. $ devlink port add netdevsim/netdevsim10 flavour pcisf controller 0 pfnum 0 Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko --- drivers/net/netdevsim/netdevsim.h | 1 + drivers/net/netdevsim/port_function.c | 95 +++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 0ea9705eda38..c70782e444d5 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -222,6 +222,7 @@ struct nsim_dev { struct list_head head; struct ida ida; struct ida pfnum_ida; + struct ida sfnum_ida; } port_functions; }; diff --git a/drivers/net/netdevsim/port_function.c b/drivers/net/netdevsim/port_function.c index 01587b54f0e0..3a90de50b152 100644 --- a/drivers/net/netdevsim/port_function.c +++ b/drivers/net/netdevsim/port_function.c @@ -13,10 +13,12 @@ struct nsim_port_function { unsigned int port_index; enum devlink_port_flavour flavour; u32 controller; + u32 sfnum; u16 pfnum; struct nsim_port_function *pf_port; /* Valid only for SF port */ u8 hw_addr[ETH_ALEN]; u8 state; /* enum devlink_port_function_state */ + int refcount; /* Counts how many sf ports are bound attached to this pf port. */ }; void nsim_dev_port_function_init(struct nsim_dev *nsim_dev) @@ -25,10 +27,13 @@ void nsim_dev_port_function_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_function_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)); @@ -119,9 +124,24 @@ nsim_devlink_port_function_alloc(struct nsim_dev *dev, const struct devlink_port 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: @@ -137,6 +157,9 @@ static void nsim_devlink_port_function_free(struct nsim_dev *dev, struct nsim_po 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; }; @@ -170,6 +193,11 @@ nsim_dev_port_port_exists(struct nsim_dev *nsim_dev, const struct devlink_port_n if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF && 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 && + tmp->sfnum == attrs->sfnum && tmp->pfnum == attrs->pfnum) + return true; } return false; } @@ -183,21 +211,71 @@ nsim_dev_devlink_port_index_lookup(const struct nsim_dev *nsim_dev, unsigned int 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_function * +pf_port_get(struct nsim_dev *nsim_dev, struct nsim_port_function *port) +{ + struct nsim_port_function *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_port = tmp; + tmp->refcount++; + return tmp; + } + return ERR_PTR(-ENOENT); +} + +static void pf_port_put(struct nsim_port_function *port) +{ + if (port->pf_port) { + port->pf_port->refcount--; + WARN_ON(port->pf_port->refcount < 0); + } + port->refcount--; + WARN_ON(port->refcount != 0); +} + static int nsim_devlink_port_function_add(struct devlink *devlink, struct nsim_dev *nsim_dev, struct nsim_port_function *port, struct netlink_ext_ack *extack) { + struct nsim_port_function *pf_port; 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_port = pf_port_get(nsim_dev, port); + if (IS_ERR(pf_port)) { + NL_SET_ERR_MSG_MOD(extack, "Fail to get pf port"); + err = PTR_ERR(pf_port); + goto pf_err; + } - port->state = DEVLINK_PORT_FUNCTION_STATE_INACTIVE; err = devlink_port_register(devlink, &port->dl_port, port->port_index); if (err) goto reg_err; @@ -213,6 +291,8 @@ static int nsim_devlink_port_function_add(struct devlink *devlink, struct nsim_d 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; } @@ -224,12 +304,14 @@ static void nsim_devlink_port_function_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, const struct devlink_port_new_attrs *attrs, @@ -266,7 +348,11 @@ int nsim_dev_devlink_port_new(struct devlink *devlink, const struct devlink_port 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, port->controller, port->pfnum, false); + if (attrs->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF) + devlink_port_attrs_pci_pf_set(&port->dl_port, port->controller, port->pfnum, false); + else + devlink_port_attrs_pci_sf_set(&port->dl_port, port->controller, port->pfnum, + port->sfnum, false); err = nsim_devlink_port_function_add(devlink, nsim_dev, port, extack); if (err) @@ -333,6 +419,7 @@ void nsim_dev_port_function_disable(struct nsim_dev *nsim_dev) * 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_function_del(nsim_dev, port); nsim_devlink_port_function_free(nsim_dev, port);