Current port flavours cover simple switches and DSA.  Add PF
and VF flavours to cover "switchdev" SR-IOV NICs.

Example devlink user space output:

$ devlink port
pci/0000:82:00.0/0: type eth netdev p4p1 flavour physical
pci/0000:82:00.0/10000: type eth netdev eth0 flavour pcie_pf pf 0
pci/0000:82:00.0/10001: type eth netdev eth1 flavour pcie_vf pf 0 vf 0
pci/0000:82:00.0/10002: type eth netdev eth2 flavour pcie_vf pf 0 vf 1

$ devlink -jp port
{
    "port": {
        "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,
        },
        "pci/0000:82:00.0/10001": {
            "type": "eth",
            "netdev": "eth1",
            "flavour": "pci_vf",
            "pf": 0,
            "vf": 0
        },
        "pci/0000:82:00.0/10002": {
            "type": "eth",
            "netdev": "eth2",
            "flavour": "pci_vf",
            "pf": 0,
            "vf": 1
        }
    }
}

Signed-off-by: Jakub Kicinski <jakub.kicin...@netronome.com>
---
 include/net/devlink.h        | 25 ++++++++++--
 include/uapi/linux/devlink.h |  5 +++
 net/core/devlink.c           | 73 +++++++++++++++++++++++++++++++-----
 3 files changed, 91 insertions(+), 12 deletions(-)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index 7f5a0bdca228..b5376ef492f1 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -42,9 +42,19 @@ struct devlink {
 struct devlink_port_attrs {
        bool set;
        enum devlink_port_flavour flavour;
-       u32 port_number; /* same value as "split group" */
-       bool split;
-       u32 split_subport_number;
+       union { /* port identifiers differ per-flavour */
+               /* PHYSICAL, CPU, DSA */
+               struct {
+                       bool split;
+                       u32 split_subport_number;
+                       u32 port_number; /* same value as "split group" */
+               };
+                /* PCI_PF, PCI_VF */
+               struct {
+                       u32 pf_number;
+                       u32 vf_number;
+               } pci;
+       };
 };
 
 struct devlink_port {
@@ -568,6 +578,9 @@ void devlink_port_attrs_set(struct devlink_port 
*devlink_port,
                            enum devlink_port_flavour flavour,
                            u32 port_number, bool split,
                            u32 split_subport_number);
+void devlink_port_attrs_pci_set(struct devlink_port *devlink_port,
+                               enum devlink_port_flavour flavour,
+                               u32 pf_number, u32 vf_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,
@@ -782,6 +795,12 @@ static inline void devlink_port_attrs_set(struct 
devlink_port *devlink_port,
 {
 }
 
+static inline void devlink_port_attrs_pci_set(struct devlink_port 
*devlink_port,
+                                             enum devlink_port_flavour flavour,
+                                             u32 pf_number, u32 vf_number)
+{
+}
+
 static inline int
 devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
                                char *name, size_t len)
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 5bb4ea67d84f..9ce76d4f640d 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -167,6 +167,8 @@ enum devlink_port_flavour {
        DEVLINK_PORT_FLAVOUR_DSA, /* Distributed switch architecture
                                   * interconnect port.
                                   */
+       DEVLINK_PORT_FLAVOUR_PCI_PF, /* PCI Physical function port */
+       DEVLINK_PORT_FLAVOUR_PCI_VF, /* PCI Physical function port */
 };
 
 enum devlink_param_cmode {
@@ -332,6 +334,9 @@ enum devlink_attr {
        DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME,    /* string */
        DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,    /* string */
 
+       DEVLINK_ATTR_PORT_PCI_PF_NUMBER,        /* u32 */
+       DEVLINK_ATTR_PORT_PCI_VF_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 a49dee67e66f..af177284830b 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -516,16 +516,35 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg,
                return 0;
        if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
                return -EMSGSIZE;
-       if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number))
-               return -EMSGSIZE;
-       if (!attrs->split)
+
+       switch (attrs->flavour) {
+       case DEVLINK_PORT_FLAVOUR_PHYSICAL:
+       case DEVLINK_PORT_FLAVOUR_CPU:
+       case DEVLINK_PORT_FLAVOUR_DSA:
+               if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER,
+                               attrs->port_number))
+                       return -EMSGSIZE;
+
+               if (attrs->split &&
+                   (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
+                                attrs->port_number) ||
+                    nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
+                                attrs->split_subport_number)))
+                       return -EMSGSIZE;
                return 0;
-       if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number))
-               return -EMSGSIZE;
-       if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
-                       attrs->split_subport_number))
-               return -EMSGSIZE;
-       return 0;
+       case DEVLINK_PORT_FLAVOUR_PCI_VF:
+               if (nla_put_u32(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER,
+                               attrs->pci.vf_number))
+                       return -EMSGSIZE;
+               /* fall through */
+       case DEVLINK_PORT_FLAVOUR_PCI_PF:
+               if (nla_put_u32(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
+                               attrs->pci.pf_number))
+                       return -EMSGSIZE;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
@@ -5410,6 +5429,9 @@ void devlink_port_attrs_set(struct devlink_port 
*devlink_port,
 {
        struct devlink_port_attrs *attrs = &devlink_port->attrs;
 
+       WARN_ON(flavour == DEVLINK_PORT_FLAVOUR_PCI_PF ||
+               flavour == DEVLINK_PORT_FLAVOUR_PCI_VF);
+
        attrs->set = true;
        attrs->flavour = flavour;
        attrs->port_number = port_number;
@@ -5419,6 +5441,32 @@ void devlink_port_attrs_set(struct devlink_port 
*devlink_port,
 }
 EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
 
+/**
+ *     devlink_port_attrs_pci_set - Set port attributes for a PCI port
+ *
+ *     @devlink_port: devlink port
+ *     @flavour: flavour of the port (PF or VF only)
+ *     @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)
+ */
+void devlink_port_attrs_pci_set(struct devlink_port *devlink_port,
+                               enum devlink_port_flavour flavour,
+                               u32 pf_number, u32 vf_number)
+{
+       struct devlink_port_attrs *attrs = &devlink_port->attrs;
+
+       WARN_ON(flavour != DEVLINK_PORT_FLAVOUR_PCI_PF &&
+               flavour != DEVLINK_PORT_FLAVOUR_PCI_VF);
+
+       attrs->set = true;
+       attrs->flavour = flavour;
+       attrs->pci.pf_number = pf_number;
+       attrs->pci.vf_number = vf_number;
+       devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
+}
+EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_set);
+
 int devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
                                    char *name, size_t len)
 {
@@ -5443,6 +5491,13 @@ 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);
+               break;
+       case DEVLINK_PORT_FLAVOUR_PCI_VF:
+               n = snprintf(name, len, "pf%uvf%u",
+                            attrs->pf_number, attrs->pci.vf_number);
+               break;
        }
 
        if (n >= len)
-- 
2.19.2

Reply via email to