PCI endpoint corresponds to a PCI device, but such device can have one more more logical device ports associated with it. We need a way to distinguish those. Add a PCI subport in the dumps and print the info in phys_port_name appropriately.
This is not equivalent to port splitting, there is no split group. It's just a way of representing multiple netdevs on a single PCI function. Note that the quality of being multiport pertains only to the PCI function itself. A PF having multiple netdevs does not mean that its VFs will also have multiple, or that VFs are associated with any particular port of a multiport VF. Example (bus 05 device has subports, bus 82 has only one port per function): $ devlink port pci/0000:05:00.0/0: type eth netdev enp5s0np0 flavour physical pci/0000:05:00.0/10000: type eth netdev enp5s0npf0s0 flavour pci_pf pf 0 subport 0 pci/0000:05:00.0/4: type eth netdev enp5s0np1 flavour physical pci/0000:05:00.0/11000: type eth netdev enp5s0npf0s1 flavour pci_pf pf 0 subport 1 pci/0000:82:00.0/0: type eth netdev p4p1 flavour physical pci/0000:82:00.0/10000: type eth netdev eth0 flavour pci_pf pf 0 $ devlink -jp port { "port": { "pci/0000:05:00.0/0": { "type": "eth", "netdev": "enp5s0np0", "flavour": "physical" }, "pci/0000:05:00.0/10000": { "type": "eth", "netdev": "enp5s0npf0s0", "flavour": "pci_pf", "pf": 0, "subport": 0 }, "pci/0000:05:00.0/4": { "type": "eth", "netdev": "enp5s0np1", "flavour": "physical" }, "pci/0000:05:00.0/11000": { "type": "eth", "netdev": "enp5s0npf0s1", "flavour": "pci_pf", "pf": 0, "subport": 1 }, "pci/0000:82:00.0/0": { "type": "eth", "netdev": "p4p1", "flavour": "physical" }, "pci/0000:82:00.0/10000": { "type": "eth", "netdev": "eth0", "flavour": "pci_pf", "pf": 0 } } } Signed-off-by: Jakub Kicinski <jakub.kicin...@netronome.com> --- .../net/ethernet/netronome/nfp/nfp_devlink.c | 6 ++-- include/net/devlink.h | 13 ++++--- include/uapi/linux/devlink.h | 1 + net/core/devlink.c | 36 ++++++++++++++++--- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index bf7fd9614152..6ad2805f1efc 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -378,12 +378,14 @@ int nfp_devlink_port_init(struct nfp_app *app, struct nfp_port *port) return nfp_devlink_port_init_phys(devlink, port); case NFP_PORT_PF_PORT: devlink_port_type_eth_set(&port->dl_port, port->netdev); - devlink_port_attrs_pci_pf_set(&port->dl_port, port->pf_id); + devlink_port_attrs_pci_pf_set(&port->dl_port, port->pf_id, + port->pf_split, + port->pf_split_id); return 0; case NFP_PORT_VF_PORT: devlink_port_type_eth_set(&port->dl_port, port->netdev); devlink_port_attrs_pci_vf_set(&port->dl_port, port->pf_id, - port->vf_id); + port->vf_id, false, 0); return 0; default: return -EINVAL; diff --git a/include/net/devlink.h b/include/net/devlink.h index 00ceff76762c..6a29ce80cb38 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -53,6 +53,8 @@ struct devlink_port_attrs { struct { u32 pf_number; u32 vf_number; + bool multiport; + u32 subport_number; } pci; }; }; @@ -579,9 +581,11 @@ void devlink_port_attrs_set(struct devlink_port *devlink_port, u32 port_number, bool split, u32 split_subport_number); void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, - u32 pf_number); + u32 pf_number, bool multiport, + u32 subport_number); void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, - u32 pf_number, u32 vf_number); + u32 pf_number, u32 vf_number, bool multiport, + u32 subport_number); int devlink_port_get_phys_port_name(struct devlink_port *devlink_port, char *name, size_t len); int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, @@ -798,13 +802,14 @@ static inline void devlink_port_attrs_set(struct devlink_port *devlink_port, static inline void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, - u32 pf_number) + u32 pf_number, bool multiport, u32 subport_number) { } static inline void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, - u32 pf_number, u32 vf_number) + u32 pf_number, u32 vf_number, bool multiport, + u32 subport_number) { } diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index 9ce76d4f640d..417ae8233cce 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -336,6 +336,7 @@ enum devlink_attr { DEVLINK_ATTR_PORT_PCI_PF_NUMBER, /* u32 */ DEVLINK_ATTR_PORT_PCI_VF_NUMBER, /* u32 */ + DEVLINK_ATTR_PORT_PCI_SUBPORT, /* u32 */ /* add new attributes above here, update the policy in devlink.c */ diff --git a/net/core/devlink.c b/net/core/devlink.c index 49216b688c5b..a7dd958be513 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -541,6 +541,11 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg, if (nla_put_u32(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci.pf_number)) return -EMSGSIZE; + + if (attrs->pci.multiport && + nla_put_u32(msg, DEVLINK_ATTR_PORT_PCI_SUBPORT, + attrs->pci.subport_number)) + return -EMSGSIZE; return 0; default: return -EINVAL; @@ -5449,15 +5454,20 @@ EXPORT_SYMBOL_GPL(devlink_port_attrs_set); * @devlink_port: devlink port * @pf_number: PCI PF number, in multi-host mapping to hosts depends * on the platform + * @multiport: PCI function has more than one logical port + * @subport_number: PCI function has more than one logical port */ void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, - u32 pf_number) + u32 pf_number, bool multiport, + u32 subport_number) { struct devlink_port_attrs *attrs = &devlink_port->attrs; attrs->set = true; attrs->flavour = DEVLINK_PORT_FLAVOUR_PCI_PF; attrs->pci.pf_number = pf_number; + attrs->pci.multiport = multiport; + attrs->pci.subport_number = subport_number; devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); } EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set); @@ -5469,9 +5479,12 @@ EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set); * @pf_number: PCI PF number, in multi-host mapping to hosts depends * on the platform * @vf_number: PCI VF number within given PF (ignored for PF itself) + * @multiport: PCI function has more than one logical port + * @subport_number: PCI function has more than one logical port */ void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, - u32 pf_number, u32 vf_number) + u32 pf_number, u32 vf_number, bool multiport, + u32 subport_number) { struct devlink_port_attrs *attrs = &devlink_port->attrs; @@ -5479,6 +5492,8 @@ void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, attrs->flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; attrs->pci.pf_number = pf_number; attrs->pci.vf_number = vf_number; + attrs->pci.multiport = multiport; + attrs->pci.subport_number = subport_number; devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); } EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set); @@ -5508,11 +5523,22 @@ int devlink_port_get_phys_port_name(struct devlink_port *devlink_port, WARN_ON(1); return -EINVAL; case DEVLINK_PORT_FLAVOUR_PCI_PF: - n = snprintf(name, len, "pf%u", attrs->pci.pf_number); + if (!attrs->pci.multiport) + n = snprintf(name, len, "pf%u", attrs->pci.pf_number); + else + n = snprintf(name, len, "pf%us%u", attrs->pci.pf_number, + attrs->pci.subport_number); break; case DEVLINK_PORT_FLAVOUR_PCI_VF: - n = snprintf(name, len, "pf%uvf%u", - attrs->pci.pf_number, attrs->pci.vf_number); + if (!attrs->pci.multiport) + n = snprintf(name, len, "pf%uvf%u", + attrs->pci.pf_number, + attrs->pci.vf_number); + else + n = snprintf(name, len, "pf%uvf%us%u", + attrs->pci.pf_number, + attrs->pci.vf_number, + attrs->pci.subport_number); break; } -- 2.19.2