From patchwork Thu Sep 17 17:20:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1366303 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=h4jqnsWM; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BskJw0mCCz9sRf for ; Fri, 18 Sep 2020 03:21:19 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726312AbgIQRVN (ORCPT ); Thu, 17 Sep 2020 13:21:13 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:4951 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726412AbgIQRUh (ORCPT ); Thu, 17 Sep 2020 13:20:37 -0400 Received: from hqpgpgate102.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 10:19:50 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate102.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 10:20:34 -0700 X-PGP-Universal: processed; by hqpgpgate102.nvidia.com on Thu, 17 Sep 2020 10:20:34 -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 17:20:33 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next v2 1/8] devlink: Introduce PCI SF port flavour and port attribute Date: Thu, 17 Sep 2020 20:20:13 +0300 Message-ID: <20200917172020.26484-2-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917172020.26484-1-parav@nvidia.com> References: <20200917081731.8363-8-parav@nvidia.com> <20200917172020.26484-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600363190; 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=h4jqnsWM68Cf5tZsjz12jwKB+WHz0dSqCjpAHih1PT+m1OwdWhoBWtrA6pmFa25+1 V15V+QezArrjqMZsGfGxUGuqfzrMiGYZJOPUDg9SF7h+Nf1oTVHyBzQMpuqgvuqRIN TqZdzmroEZ8CrH9GREzQ2Vt03A1WkDzrJyBhhSF2jPt/IHjPeIH8cqTYsZDD0jkeG+ WeaUGKmO3ZNjkxyX9mLINHCvYSDX99L1810svC4NksMplvQjgrIhYU2UfGVhAYhhVh C2EkEbA2nfzMqePPNzsHPeEV3SS9nXYX2bm4m195VbHO1KsKYF1fSlbm4lXVEoa8LJ SpAW8iuPF+guQ== 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 17:20:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1366304 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=Vdal5s2v; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BskK968flz9sRR for ; Fri, 18 Sep 2020 03:21:33 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726400AbgIQRV3 (ORCPT ); Thu, 17 Sep 2020 13:21:29 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:11034 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726419AbgIQRUh (ORCPT ); Thu, 17 Sep 2020 13:20:37 -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 10:19:06 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 10:20:35 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 10:20:35 -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 17:20:34 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next v2 2/8] devlink: Support add and delete devlink port Date: Thu, 17 Sep 2020 20:20:14 +0300 Message-ID: <20200917172020.26484-3-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917172020.26484-1-parav@nvidia.com> References: <20200917081731.8363-8-parav@nvidia.com> <20200917172020.26484-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600363146; 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=Vdal5s2vdz95y61RxMBOm/9pRhv0PrNS2xN5j9NLBppQ+f9DQkrCA4xd09AJvCjxW U6IzXmVUjoN58XAzZHWeU+5TtAy3ogCd5MBsFNtSqhLisuKGfmYoYFHGWWcBa0SihJ ogwIOy9fxYaNJKkEP1+ciCooBOIxizLQXylvohRVk6hW2AAqgsqyQlGx8KA9pSKjln Y3YOCXgpNwcm/mUdu1zmckJa9SJ8agbqoLYoEKeOCmeb73KGVaiZOg23yMNorfSAXE SwlSZ0ASei2KWw/V3sw6dq+pqCQncsdWao5Yv5aN/IHMiszzLLbYg0/mguu12/ymHt 8w1bAXdLNAqyg== 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 17:20:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1366311 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=haZn+MSd; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BskRT5m5fz9sRR for ; Fri, 18 Sep 2020 03:27:01 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726400AbgIQR0O (ORCPT ); Thu, 17 Sep 2020 13:26:14 -0400 Received: from hqnvemgate26.nvidia.com ([216.228.121.65]:19683 "EHLO hqnvemgate26.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726420AbgIQRUk (ORCPT ); Thu, 17 Sep 2020 13:20:40 -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 10:20:22 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 10:20:35 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 10:20:35 -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 17:20:34 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next v2 3/8] devlink: Prepare code to fill multiple port function attributes Date: Thu, 17 Sep 2020 20:20:15 +0300 Message-ID: <20200917172020.26484-4-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917172020.26484-1-parav@nvidia.com> References: <20200917081731.8363-8-parav@nvidia.com> <20200917172020.26484-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600363222; 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=haZn+MSdBhqNjgYmKAl1xELqi0tiLV/vNbu5vzn5aH/f+opOm5unbY9LsJxrshZn+ vq+/iJKcSECReg39ZupFPPCMWz35S45pMroSlGTu+Sqje6d+msqD6a+GPoa9VR+FWC WRQpBbHLbjbrLMvyVHOeHf1NbX6qslv/rfs7avNPaXNk+RJrvxmrRM6ptS//Zj4sa3 XOAmvtDjUUhRaRbkHFfiivxQjcbw6QstYWBcV/yXMFLnxb7Aqtc5UhoV7hju3Gwi3I FhGICoI4pZIwuiIDHAdmfslN+DDR4f4rlFz9yco56MXkHXet3iMI9HAcToqZ4xmxp0 phruXkNRFMQLQ== 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 17:20:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1366310 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=dpt1azqr; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BskPz3DnDz9sSn for ; Fri, 18 Sep 2020 03:25:43 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726424AbgIQRZe (ORCPT ); Thu, 17 Sep 2020 13:25:34 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:4959 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726434AbgIQRUp (ORCPT ); Thu, 17 Sep 2020 13:20:45 -0400 Received: from hqpgpgate102.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 10:19:52 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate102.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 10:20:36 -0700 X-PGP-Universal: processed; by hqpgpgate102.nvidia.com on Thu, 17 Sep 2020 10:20:36 -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 17:20:35 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next v2 4/8] devlink: Support get and set state of port function Date: Thu, 17 Sep 2020 20:20:16 +0300 Message-ID: <20200917172020.26484-5-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917172020.26484-1-parav@nvidia.com> References: <20200917081731.8363-8-parav@nvidia.com> <20200917172020.26484-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600363193; bh=0VV+T343EvRTzRSQ1+DMysLKVM10VNxPneonOi0VSKA=; 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=dpt1azqr1dEwBXgRFh8VA7tzRR1H3OF4iQvSQFlcqK+48W/UvCzXU0mIjymrpmUYz lH0daVoGZOccUGGtc8auP1apCbJ8uJs3NeKUTeUO3z6oxtCWF3wc1DsYJrrD2iCEie p4jcpx92yQsEDaWe9aYmhLtqBIiQyRvDuZ9eyDEKoUCzq8hxGjuv7QHgnGwwTGDzaN sjM1uqN+NfhfRvvaAjuRQjgyxbV2zJGHOMq4S1Dyfmbk3uCLEUnHquFKM1BcSlvaXT BhSCasirq2A729g2P/+iMAMDFGnkqnbtqDB0+G6YKie3jc1Bpvf7mS7gw8ny6Yvsqv oOYEIL9Zx5A5g== 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 eth0 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 17:20:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1366309 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=Y2eq5M2x; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BskN45xzyz9sPB for ; Fri, 18 Sep 2020 03:24:04 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726518AbgIQRYB (ORCPT ); Thu, 17 Sep 2020 13:24:01 -0400 Received: from hqnvemgate26.nvidia.com ([216.228.121.65]:19693 "EHLO hqnvemgate26.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726440AbgIQRUp (ORCPT ); Thu, 17 Sep 2020 13:20:45 -0400 Received: from hqpgpgate102.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate26.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 10:20:24 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate102.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 10:20:37 -0700 X-PGP-Universal: processed; by hqpgpgate102.nvidia.com on Thu, 17 Sep 2020 10:20:37 -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 17:20:36 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next v2 5/8] netdevsim: Add support for add and delete of a PCI PF port Date: Thu, 17 Sep 2020 20:20:17 +0300 Message-ID: <20200917172020.26484-6-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917172020.26484-1-parav@nvidia.com> References: <20200917081731.8363-8-parav@nvidia.com> <20200917172020.26484-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600363224; bh=65XMLc42P1oYsa7VBLr1ijWhx7VYy4lRDGJcYcmLhmw=; 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=Y2eq5M2x2xqzSrI7V9bOq57bqp8cF6JneKv1FHXE2uwKyfa7ZS9UJkA7jGHuQfTZZ dpFLNyhq3OcIgWU+Gm5fmGqLLCTukA3NjniRnFjlCVRQeHuxN8iK6NdGa/Vpgd+zci C5DOTI7DaZlZcA4N8xghCAJgz5SHIzJyb5qD8LbOJRRkx76nCU1Ti4byi7/4t9Scth /jnNoH3xkUZqHq6UOM8wJwmbvJjxxucgTWA/zlENHITuPPaer7mHJ4UueUi7wx5wLc UOMNqK8Q3+eykIpPmz+0V33usNrfuhlknJYYx0W5Bu2VH1eYPZtk/GVQ+PJYtjozsG fVL+Cxv+1PwxA== 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 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 --- Changelog: v1->v2: - Fixed extra semicolon at end of switch case reportec by coccinelle --- 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..4f3e9cc9489f --- /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 17:20:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1366307 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=CTfnhaF1; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BskMr1M4Dz9sRR for ; Fri, 18 Sep 2020 03:23:52 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726315AbgIQRXr (ORCPT ); Thu, 17 Sep 2020 13:23:47 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:11040 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726448AbgIQRUp (ORCPT ); Thu, 17 Sep 2020 13:20:45 -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 10:19:08 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 10:20:37 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 10:20:37 -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 17:20:36 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next v2 6/8] netdevsim: Simulate get/set hardware address of a PCI port Date: Thu, 17 Sep 2020 20:20:18 +0300 Message-ID: <20200917172020.26484-7-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917172020.26484-1-parav@nvidia.com> References: <20200917081731.8363-8-parav@nvidia.com> <20200917172020.26484-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600363148; bh=iHcxwDuKnwffefMnVImS2YPfehOunDT3K3S3AnH/MTA=; 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=CTfnhaF1mmHMfky/fUTH8zsFZrUapzFUMP+X1wVJpdg3tjr/VRc2o1NqgwxvF0xf7 y4rtsiDs8HN90JVc9viRWp7swCzOt8xxfgYd90K9f+tTw8phRk9PgF3AKIixRxBbKx RaAKYWrRQeY1DPFbYvHmfJrSWeBU+MI6pw2VsS4TG0fYCs1CLwt7tgw1MJOKrTf4oJ evE/Bm6wQd8svgFA+HC9kaEwOUEQyi1b8H8zUjmSk3//FZNkE3QpiaDE9nNBORNDMZ gSsG8m49DriowPZd/bAbF0UOe4btFxK2lLlmk0TKSjHndv5UYKPhYA90mjPkB2J0KY CGOxr8fU09NCA== 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 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 4f3e9cc9489f..6feeeaf19ce8 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 17:20:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1366343 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=fsDfLpvB; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Bslyq71W4z9sRK for ; Fri, 18 Sep 2020 04:35:47 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726476AbgIQRZq (ORCPT ); Thu, 17 Sep 2020 13:25:46 -0400 Received: from hqnvemgate26.nvidia.com ([216.228.121.65]:19696 "EHLO hqnvemgate26.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726467AbgIQRUp (ORCPT ); Thu, 17 Sep 2020 13:20:45 -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 10:20:25 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 10:20:38 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Thu, 17 Sep 2020 10:20:38 -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 17:20:37 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next v2 7/8] netdevsim: Simulate port function state for a PCI port Date: Thu, 17 Sep 2020 20:20:19 +0300 Message-ID: <20200917172020.26484-8-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917172020.26484-1-parav@nvidia.com> References: <20200917081731.8363-8-parav@nvidia.com> <20200917172020.26484-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600363225; bh=7zbtMksJlUe+QCzGhSuPP6d3NskPns7dL9cfZ814AGo=; 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=fsDfLpvBvfpBW2Sp9Et/t/SnbQ5vavW/fq301ZDUbUBIuRcKrteycgU4IzTNvWROF lTc/gV7/qNlYr75vgGnvm1FG7EnwaysM3D/X0W79fhAdd4Zl87CAh5fjok2MJp8ZWq 2XF8X+30SqNsa4huoeh9GJTH0ZQIqR7S0iv+S2AB5xJ8O9O6LYB5NUdgW0ubd945ev mdEfldmV+GkysAGrAVPY7fu/G1TbydOXmJAEnVpu4cNRH1+odGsbcPgjdyBeMfMHQL WEENfcmM/H5f21s1Wf7/berWhMFpgq/hap44bf3pJ0Fz54kaowtpLFazyCgNQhXfmm x4aBW9KhO+2fg== 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 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 6feeeaf19ce8..99581d3d15fe 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 17:20:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 1366306 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=AIcJJbWq; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BskLV0zVJz9sPB for ; Fri, 18 Sep 2020 03:22:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726518AbgIQRW2 (ORCPT ); Thu, 17 Sep 2020 13:22:28 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:4967 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726470AbgIQRUt (ORCPT ); Thu, 17 Sep 2020 13:20:49 -0400 Received: from hqpgpgate102.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Thu, 17 Sep 2020 10:19:55 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate102.nvidia.com (PGP Universal service); Thu, 17 Sep 2020 10:20:39 -0700 X-PGP-Universal: processed; by hqpgpgate102.nvidia.com on Thu, 17 Sep 2020 10:20:39 -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 17:20:38 +0000 From: Parav Pandit To: , , CC: Parav Pandit , Jiri Pirko Subject: [PATCH net-next v2 8/8] netdevsim: Add support for add and delete PCI SF port Date: Thu, 17 Sep 2020 20:20:20 +0300 Message-ID: <20200917172020.26484-9-parav@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200917172020.26484-1-parav@nvidia.com> References: <20200917081731.8363-8-parav@nvidia.com> <20200917172020.26484-1-parav@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.124.1.5] X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To HQMAIL107.nvidia.com (172.20.187.13) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1600363195; bh=/AiavoDGmWDAXWAOOXL6PjYKYzFMPXnr8WU9tXlwyUI=; 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=AIcJJbWqaDwmilJtlDkz7F+oGHAUvf5J4d8IrgYHJvv3+q/xHx7ekGZ3bbOnFBGBP xl/WrStHi7UFcOUxVt3JpZN4oJF0uSRkJPLgkO/5ndBu/7eFgHZfrZpCoReKkUMCzK 0m1jEhs19im20eajtyFFypzWyckPuRMajC8j0QetCwzSsksrHxsXEbS7ohJIKOnfXh 8lZFBA2y3/LDluvE05NGiolTBsw6neneqAXwjoGH1iz6WFaErZt4EgewTJq7XMY9/I h6tzHYg6bZQppjZIxnusrloJGm6wZtIGz1FT7NN2704UmmS1suOlvDpZ1SxJG3H4qU 67PG50+hcxeog== 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. $ 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 99581d3d15fe..e1812acd55b4 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);