A vdev may represent a network device, so it may be linked to
a devlink port.
Added devlink_port_register_with_vdev to allow vdev-port linkage.

Example:

$ devlink vdev show pci/0000:03:00.0/1 -jp
{
    "vdev": {
        "pci/0000:03:00.0/1": {
            "flavour": "pcivf",
            "pf": 0,
            "vf": 0,
            "port_index": 1
        }
    }
}
$ devlink vdev show pci/0000:03:00.0/1
pci/0000:03:00.0/1: flavour pcivf pf 0 vf 0 port_index 1

$ devlink port show pci/0000:03:00.0/1
pci/0000:03:00.0/1: type eth netdev ens2f0_0 flavour pcivf pfnum 0 vfnum 0 
vdev_index 1

Signed-off-by: Yuval Avnery <yuva...@mellanox.com>
Acked-by: Jiri Pirko <j...@mellanox.com>
---
 include/net/devlink.h |  5 ++++
 net/core/devlink.c    | 53 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index ab7e316ea758..138d33275963 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -90,6 +90,7 @@ struct devlink_port {
        void *type_dev;
        struct devlink_port_attrs attrs;
        struct delayed_work type_warn_dw;
+       struct devlink_vdev *devlink_vdev; /* linked vdev */
 };
 
 struct devlink_vdev_pci_pf_attrs {
@@ -806,6 +807,10 @@ void devlink_free(struct devlink *devlink);
 int devlink_port_register(struct devlink *devlink,
                          struct devlink_port *devlink_port,
                          unsigned int port_index);
+int devlink_port_register_with_vdev(struct devlink *devlink,
+                                   struct devlink_port *devlink_port,
+                                   unsigned int port_index,
+                                   struct devlink_vdev *devlink_vdev);
 void devlink_port_unregister(struct devlink_port *devlink_port);
 void devlink_port_type_eth_set(struct devlink_port *devlink_port,
                               struct net_device *netdev);
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 0a201a373da9..2fffbd37e710 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -37,6 +37,7 @@ struct devlink_vdev {
        unsigned int index;
        const struct devlink_vdev_ops *ops;
        struct devlink_vdev_attrs attrs;
+       struct devlink_port *devlink_port; /* linked port */
        void *priv;
 };
 
@@ -664,6 +665,10 @@ static int devlink_nl_port_fill(struct sk_buff *msg, 
struct devlink *devlink,
                        goto nla_put_failure_type_locked;
        }
        spin_unlock_bh(&devlink_port->type_lock);
+       if (devlink_port->devlink_vdev)
+               if (nla_put_u32(msg, DEVLINK_ATTR_VDEV_INDEX,
+                               devlink_port->devlink_vdev->index))
+                       goto nla_put_failure;
        if (devlink_nl_port_attrs_put(msg, devlink_port))
                goto nla_put_failure;
 
@@ -738,6 +743,11 @@ static int devlink_nl_vdev_fill(struct sk_buff *msg, 
struct devlink *devlink,
                break;
        }
 
+       if (devlink_vdev->devlink_port)
+               if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
+                               devlink_vdev->devlink_port->index))
+                       goto nla_put_failure;
+
        genlmsg_end(msg, hdr);
        return 0;
 
@@ -6582,11 +6592,12 @@ static void devlink_port_type_warn_cancel(struct 
devlink_port *devlink_port)
 }
 
 /**
- *     devlink_port_register - Register devlink port
+ *     devlink_port_register_with_vdev - Register devlink port
  *
  *     @devlink: devlink
  *     @devlink_port: devlink port
  *     @port_index: driver-specific numerical identifier of the port
+ *     @devlink_vdev: vdev to link with the port
  *
  *     Register devlink port with provided port index. User can use
  *     any indexing, even hw-related one. devlink_port structure
@@ -6594,9 +6605,10 @@ static void devlink_port_type_warn_cancel(struct 
devlink_port *devlink_port)
  *     Note that the caller should take care of zeroing the devlink_port
  *     structure.
  */
-int devlink_port_register(struct devlink *devlink,
-                         struct devlink_port *devlink_port,
-                         unsigned int port_index)
+int devlink_port_register_with_vdev(struct devlink *devlink,
+                                   struct devlink_port *devlink_port,
+                                   unsigned int port_index,
+                                   struct devlink_vdev *devlink_vdev)
 {
        mutex_lock(&devlink->lock);
        if (devlink_port_index_exists(devlink, port_index)) {
@@ -6606,15 +6618,42 @@ int devlink_port_register(struct devlink *devlink,
        devlink_port->devlink = devlink;
        devlink_port->index = port_index;
        devlink_port->registered = true;
+       devlink_port->devlink_vdev = devlink_vdev;
        spin_lock_init(&devlink_port->type_lock);
        list_add_tail(&devlink_port->list, &devlink->port_list);
        INIT_LIST_HEAD(&devlink_port->param_list);
        mutex_unlock(&devlink->lock);
        INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
        devlink_port_type_warn_schedule(devlink_port);
+       if (devlink_vdev) {
+               devlink_vdev->devlink_port = devlink_port;
+               devlink_vdev_notify(devlink_vdev, DEVLINK_CMD_VDEV_NEW);
+       }
        devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
        return 0;
 }
+EXPORT_SYMBOL_GPL(devlink_port_register_with_vdev);
+
+/**
+ *     devlink_port_register - Register devlink port
+ *
+ *     @devlink: devlink
+ *     @devlink_port: devlink port
+ *     @port_index: driver-specific numerical identifier of the port
+ *
+ *     Register devlink port with provided port index. User can use
+ *     any indexing, even hw-related one. devlink_port structure
+ *     is convenient to be embedded inside user driver private structure.
+ *     Note that the caller should take care of zeroing the devlink_port
+ *     structure.
+ */
+int devlink_port_register(struct devlink *devlink,
+                         struct devlink_port *devlink_port,
+                         unsigned int port_index)
+{
+       return devlink_port_register_with_vdev(devlink, devlink_port,
+                                              port_index, NULL);
+}
 EXPORT_SYMBOL_GPL(devlink_port_register);
 
 /**
@@ -6624,9 +6663,14 @@ EXPORT_SYMBOL_GPL(devlink_port_register);
  */
 void devlink_port_unregister(struct devlink_port *devlink_port)
 {
+       struct devlink_vdev *devlink_vdev = devlink_port->devlink_vdev;
        struct devlink *devlink = devlink_port->devlink;
 
        devlink_port_type_warn_cancel(devlink_port);
+       if (devlink_vdev) {
+               devlink_vdev->devlink_port = NULL;
+               devlink_vdev_notify(devlink_vdev, DEVLINK_CMD_VDEV_NEW);
+       }
        devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
        mutex_lock(&devlink->lock);
        list_del(&devlink_port->list);
@@ -6926,6 +6970,7 @@ void devlink_vdev_destroy(struct devlink_vdev 
*devlink_vdev)
 {
        struct devlink *devlink = devlink_vdev->devlink;
 
+       WARN_ON(devlink_vdev->devlink_port);
        devlink_vdev_notify(devlink_vdev, DEVLINK_CMD_VDEV_DEL);
        mutex_lock(&devlink->lock);
        list_del(&devlink_vdev->list);
-- 
2.17.1

Reply via email to