]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net/mlx5: Add a shared devlink instance for PFs on same chip
authorJiri Pirko <jiri@nvidia.com>
Thu, 12 Mar 2026 10:04:07 +0000 (11:04 +0100)
committerJakub Kicinski <kuba@kernel.org>
Sat, 14 Mar 2026 20:08:51 +0000 (13:08 -0700)
Use the previously introduced shared devlink infrastructure to create
a shared devlink instance for mlx5 PFs that reside on the same physical
chip. The shared instance is identified by the chip's serial number
extracted from PCI VPD (V3 keyword, with fallback to serial number
for older devices).

Each PF that probes calls mlx5_shd_init() which extracts the chip serial
number and uses devlink_shd_get() to get or create the shared instance.
When a PF is removed, mlx5_shd_uninit() calls devlink_shd_put()
to release the reference. The shared instance is automatically destroyed
when the last PF is removed.

Make the PF devlink instances nested in this shared devlink instance,
allowing userspace to identify which PFs belong to the same physical
chip.

Example:

pci/0000:08:00.0: index 0
  nested_devlink:
    auxiliary/mlx5_core.eth.0
devlink_index/1: index 1
  nested_devlink:
    pci/0000:08:00.0
    pci/0000:08:00.1
auxiliary/mlx5_core.eth.0: index 2
pci/0000:08:00.1: index 3
  nested_devlink:
    auxiliary/mlx5_core.eth.1
auxiliary/mlx5_core.eth.1: index 4

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Link: https://patch.msgid.link/20260312100407.551173-14-jiri@resnulli.us
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/Makefile
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h [new file with mode: 0644]
include/linux/mlx5/driver.h

index 8ffa286a18f5d443b15381e0240d5bd9039bb3f3..d39fe9c4a87cd9dd95e686d1937ae772af6dd7af 100644 (file)
@@ -16,8 +16,9 @@ mlx5_core-y :=        main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
                transobj.o vport.o sriov.o fs_cmd.o fs_core.o pci_irq.o \
                fs_counters.o fs_ft_pool.o rl.o lag/debugfs.o lag/lag.o dev.o events.o wq.o lib/gid.o \
                lib/devcom.o lib/pci_vsc.o lib/dm.o lib/fs_ttc.o diag/fs_tracepoint.o \
-               diag/fw_tracer.o diag/crdump.o devlink.o diag/rsc_dump.o diag/reporter_vnic.o \
-               fw_reset.o qos.o lib/tout.o lib/aso.o wc.o fs_pool.o lib/nv_param.o
+               diag/fw_tracer.o diag/crdump.o devlink.o sh_devlink.o diag/rsc_dump.o \
+               diag/reporter_vnic.o fw_reset.o qos.o lib/tout.o lib/aso.o wc.o fs_pool.o \
+               lib/nv_param.o
 
 #
 # Netdev basic
index fdc3ba20912e4fbc53c65825c62e868996eff56d..1c35c3fc3bb3d2eb7c584d09562e2e609ee0a4fa 100644 (file)
@@ -74,6 +74,7 @@
 #include "mlx5_irq.h"
 #include "hwmon.h"
 #include "lag/lag.h"
+#include "sh_devlink.h"
 
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver");
@@ -1520,10 +1521,16 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
        int err;
 
        devl_lock(devlink);
+       if (dev->shd) {
+               err = devl_nested_devlink_set(dev->shd, devlink);
+               if (err)
+                       goto unlock;
+       }
        devl_register(devlink);
        err = mlx5_init_one_devl_locked(dev);
        if (err)
                devl_unregister(devlink);
+unlock:
        devl_unlock(devlink);
        return err;
 }
@@ -2005,6 +2012,13 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                goto pci_init_err;
        }
 
+       err = mlx5_shd_init(dev);
+       if (err) {
+               mlx5_core_err(dev, "mlx5_shd_init failed with error code %d\n",
+                             err);
+               goto shd_init_err;
+       }
+
        err = mlx5_init_one(dev);
        if (err) {
                mlx5_core_err(dev, "mlx5_init_one failed with error code %d\n",
@@ -2018,6 +2032,8 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return 0;
 
 err_init_one:
+       mlx5_shd_uninit(dev);
+shd_init_err:
        mlx5_pci_close(dev);
 pci_init_err:
        mlx5_mdev_uninit(dev);
@@ -2039,6 +2055,7 @@ static void remove_one(struct pci_dev *pdev)
        mlx5_drain_health_wq(dev);
        mlx5_sriov_disable(pdev, false);
        mlx5_uninit_one(dev);
+       mlx5_shd_uninit(dev);
        mlx5_pci_close(dev);
        mlx5_mdev_uninit(dev);
        mlx5_adev_idx_free(dev->priv.adev_idx);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
new file mode 100644 (file)
index 0000000..bc33f95
--- /dev/null
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include <linux/mlx5/driver.h>
+#include <net/devlink.h>
+
+#include "sh_devlink.h"
+
+static const struct devlink_ops mlx5_shd_ops = {
+};
+
+int mlx5_shd_init(struct mlx5_core_dev *dev)
+{
+       u8 *vpd_data __free(kfree) = NULL;
+       struct pci_dev *pdev = dev->pdev;
+       unsigned int vpd_size, kw_len;
+       struct devlink *devlink;
+       char *sn, *end;
+       int start;
+       int err;
+
+       if (!mlx5_core_is_pf(dev))
+               return 0;
+
+       vpd_data = pci_vpd_alloc(pdev, &vpd_size);
+       if (IS_ERR(vpd_data)) {
+               err = PTR_ERR(vpd_data);
+               return err == -ENODEV ? 0 : err;
+       }
+       start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size, "V3", &kw_len);
+       if (start < 0) {
+               /* Fall-back to SN for older devices. */
+               start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
+                                                    PCI_VPD_RO_KEYWORD_SERIALNO, &kw_len);
+               if (start < 0)
+                       return -ENOENT;
+       }
+       sn = kstrndup(vpd_data + start, kw_len, GFP_KERNEL);
+       if (!sn)
+               return -ENOMEM;
+       /* Firmware may return spaces at the end of the string, strip it. */
+       end = strchrnul(sn, ' ');
+       *end = '\0';
+
+       /* Get or create shared devlink instance */
+       devlink = devlink_shd_get(sn, &mlx5_shd_ops, 0, pdev->dev.driver);
+       kfree(sn);
+       if (!devlink)
+               return -ENOMEM;
+
+       dev->shd = devlink;
+       return 0;
+}
+
+void mlx5_shd_uninit(struct mlx5_core_dev *dev)
+{
+       if (!dev->shd)
+               return;
+
+       devlink_shd_put(dev->shd);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
new file mode 100644 (file)
index 0000000..8ab8d69
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#ifndef __MLX5_SH_DEVLINK_H__
+#define __MLX5_SH_DEVLINK_H__
+
+#include <linux/mlx5/driver.h>
+
+int mlx5_shd_init(struct mlx5_core_dev *dev);
+void mlx5_shd_uninit(struct mlx5_core_dev *dev);
+
+#endif /* __MLX5_SH_DEVLINK_H__ */
index 04dcd09f7517b226f9a98afd2ed340395093114c..1268fcf35ec7427b22b50ccea43a883fbe248e91 100644 (file)
@@ -798,6 +798,7 @@ struct mlx5_core_dev {
        enum mlx5_wc_state wc_state;
        /* sync write combining state */
        struct mutex wc_state_lock;
+       struct devlink *shd;
 };
 
 struct mlx5_db {