public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip
@ 2026-03-12 10:03 Jiri Pirko
  2026-03-12 10:03 ` [PATCH net-next v4 01/13] devlink: expose devlink instance index over netlink Jiri Pirko
                   ` (13 more replies)
  0 siblings, 14 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Multiple PFs on a network adapter often reside on the same physical
chip, running a single firmware. Some resources and configurations
are inherently shared among these PFs - PTP clocks, VF group rates,
firmware parameters, and others. Today there is no good object in
the devlink model to attach these chip-wide configuration knobs to.
Drivers resort to workarounds like pinning shared state to PF0 or
maintaining ad-hoc internal structures (e.g., ice_adapter) that are
invisible to userspace.

This problem was discussed extensively starting with Przemek Kitszel's
"whole device devlink instance" RFC for the ice driver [1]. Several
approaches for representing the parent instance were considered:
using a partial PCI BDF as the dev_name (breaks when PFs have different
BDFs in VMs), creating a per-driver bus, using auxiliary devices, or
using faux devices. All of these required a backing struct device for
the parent devlink instance, which does not naturally exist - there is
no PCI device that represents the chip as a whole.

This patchset takes a different approach: allow devlink instances to
exist without any backing struct device. The instance is identified
purely by its internal index, exposed over devlin netlink. This avoids
fabricating fake devices and keeps the devlink handle semantics clean.

The first ten patches prepare the devlink core for device-less
instances by decoupling the handle from the parent device. The last
three introduce the shared devlink infrastructure and its first user
in the mlx5 driver.

Example output showing the shared instance and nesting:

  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

[1] https://lore.kernel.org/netdev/20250219164410.35665-1-przemyslaw.kitszel@intel.com/

---
Decoupled from "devlink and mlx5: Support cross-function rate scheduling"
patchset to maintain 15-patches limit.

See individual patches for changelog.

Jiri Pirko (13):
  devlink: expose devlink instance index over netlink
  devlink: add helpers to get bus_name/dev_name
  devlink: avoid extra iterations when found devlink is not registered
  devlink: allow to use devlink index as a command handle
  devlink: support index-based lookup via bus_name/dev_name handle
  devlink: support index-based notification filtering
  devlink: introduce __devlink_alloc() with dev driver pointer
  devlink: add devlink_dev_driver_name() helper and use it in trace
    events
  devlink: add devl_warn() helper and use it in port warnings
  devlink: allow devlink instance allocation without a backing device
  devlink: introduce shared devlink instance for PFs on same chip
  documentation: networking: add shared devlink documentation
  net/mlx5: Add a shared devlink instance for PFs on same chip

 Documentation/netlink/specs/devlink.yaml      |  58 +++
 .../networking/devlink/devlink-shared.rst     |  97 +++++
 Documentation/networking/devlink/index.rst    |   1 +
 .../net/ethernet/mellanox/mlx5/core/Makefile  |   5 +-
 .../net/ethernet/mellanox/mlx5/core/main.c    |  17 +
 .../ethernet/mellanox/mlx5/core/sh_devlink.c  |  61 +++
 .../ethernet/mellanox/mlx5/core/sh_devlink.h  |  12 +
 include/linux/mlx5/driver.h                   |   1 +
 include/net/devlink.h                         |  10 +
 include/trace/events/devlink.h                |  36 +-
 include/uapi/linux/devlink.h                  |   4 +
 net/devlink/Makefile                          |   2 +-
 net/devlink/core.c                            |  91 ++++-
 net/devlink/dev.c                             |   8 +-
 net/devlink/devl_internal.h                   |  34 +-
 net/devlink/netlink.c                         |  52 ++-
 net/devlink/netlink_gen.c                     | 355 +++++++++++-------
 net/devlink/port.c                            |  19 +-
 net/devlink/sh_dev.c                          | 161 ++++++++
 19 files changed, 815 insertions(+), 209 deletions(-)
 create mode 100644 Documentation/networking/devlink/devlink-shared.rst
 create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
 create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
 create mode 100644 net/devlink/sh_dev.c

-- 
2.51.1


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 01/13] devlink: expose devlink instance index over netlink
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
@ 2026-03-12 10:03 ` Jiri Pirko
  2026-03-12 10:03 ` [PATCH net-next v4 02/13] devlink: add helpers to get bus_name/dev_name Jiri Pirko
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Each devlink instance has an internally assigned index used for xarray
storage. Expose it as a new DEVLINK_ATTR_INDEX uint attribute alongside
the existing bus_name and dev_name handle.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 Documentation/netlink/specs/devlink.yaml | 5 +++++
 include/uapi/linux/devlink.h             | 2 ++
 net/devlink/devl_internal.h              | 2 ++
 net/devlink/port.c                       | 1 +
 4 files changed, 10 insertions(+)

diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml
index 837112da6738..1bed67a0eefb 100644
--- a/Documentation/netlink/specs/devlink.yaml
+++ b/Documentation/netlink/specs/devlink.yaml
@@ -867,6 +867,10 @@ attribute-sets:
         type: flag
         doc: Request restoring parameter to its default value.
         value: 183
+      -
+        name: index
+        type: uint
+        doc: Unique devlink instance index.
   -
     name: dl-dev-stats
     subset-of: devlink
@@ -1311,6 +1315,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - reload-failed
             - dev-stats
       dump:
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index e7d6b6d13470..1ba3436db4ae 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -642,6 +642,8 @@ enum devlink_attr {
 	DEVLINK_ATTR_PARAM_VALUE_DEFAULT,	/* dynamic */
 	DEVLINK_ATTR_PARAM_RESET_DEFAULT,	/* flag */
 
+	DEVLINK_ATTR_INDEX,			/* uint */
+
 	/* Add new attributes above here, update the spec in
 	 * Documentation/netlink/specs/devlink.yaml and re-generate
 	 * net/devlink/netlink_gen.c.
diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index 1377864383bc..31fa98af418e 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -178,6 +178,8 @@ devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
 		return -EMSGSIZE;
 	if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
 		return -EMSGSIZE;
+	if (nla_put_uint(msg, DEVLINK_ATTR_INDEX, devlink->index))
+		return -EMSGSIZE;
 	return 0;
 }
 
diff --git a/net/devlink/port.c b/net/devlink/port.c
index 93d8a25bb920..1ff609571ea4 100644
--- a/net/devlink/port.c
+++ b/net/devlink/port.c
@@ -222,6 +222,7 @@ size_t devlink_nl_port_handle_size(struct devlink_port *devlink_port)
 
 	return nla_total_size(strlen(devlink->dev->bus->name) + 1) /* DEVLINK_ATTR_BUS_NAME */
 	     + nla_total_size(strlen(dev_name(devlink->dev)) + 1) /* DEVLINK_ATTR_DEV_NAME */
+	     + nla_total_size(8) /* DEVLINK_ATTR_INDEX */
 	     + nla_total_size(4); /* DEVLINK_ATTR_PORT_INDEX */
 }
 
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 02/13] devlink: add helpers to get bus_name/dev_name
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
  2026-03-12 10:03 ` [PATCH net-next v4 01/13] devlink: expose devlink instance index over netlink Jiri Pirko
@ 2026-03-12 10:03 ` Jiri Pirko
  2026-03-12 10:03 ` [PATCH net-next v4 03/13] devlink: avoid extra iterations when found devlink is not registered Jiri Pirko
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Introduce devlink_bus_name() and devlink_dev_name() helpers and
convert all direct accesses to devlink->dev->bus->name and
dev_name(devlink->dev) to use them.

This prepares for dev-less devlink instances where these helpers
will be extended to handle the missing device.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v2->v3:
- don't store bus_name/dev_name in devlink struct
---
 include/net/devlink.h          |  2 ++
 include/trace/events/devlink.h | 24 ++++++++++++------------
 net/devlink/core.c             | 12 ++++++++++++
 net/devlink/devl_internal.h    |  8 ++++----
 net/devlink/netlink.c          |  4 ++--
 net/devlink/port.c             |  4 ++--
 6 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index cb839e0435a1..0afb0958b910 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -1611,6 +1611,8 @@ struct devlink_ops {
 void *devlink_priv(struct devlink *devlink);
 struct devlink *priv_to_devlink(void *priv);
 struct device *devlink_to_dev(const struct devlink *devlink);
+const char *devlink_bus_name(const struct devlink *devlink);
+const char *devlink_dev_name(const struct devlink *devlink);
 
 /* Devlink instance explicit locking */
 void devl_lock(struct devlink *devlink);
diff --git a/include/trace/events/devlink.h b/include/trace/events/devlink.h
index f241e204fe6b..32304ce9ad15 100644
--- a/include/trace/events/devlink.h
+++ b/include/trace/events/devlink.h
@@ -21,8 +21,8 @@ TRACE_EVENT(devlink_hwmsg,
 	TP_ARGS(devlink, incoming, type, buf, len),
 
 	TP_STRUCT__entry(
-		__string(bus_name, devlink_to_dev(devlink)->bus->name)
-		__string(dev_name, dev_name(devlink_to_dev(devlink)))
+		__string(bus_name, devlink_bus_name(devlink))
+		__string(dev_name, devlink_dev_name(devlink))
 		__string(driver_name, devlink_to_dev(devlink)->driver->name)
 		__field(bool, incoming)
 		__field(unsigned long, type)
@@ -55,8 +55,8 @@ TRACE_EVENT(devlink_hwerr,
 	TP_ARGS(devlink, err, msg),
 
 	TP_STRUCT__entry(
-		__string(bus_name, devlink_to_dev(devlink)->bus->name)
-		__string(dev_name, dev_name(devlink_to_dev(devlink)))
+		__string(bus_name, devlink_bus_name(devlink))
+		__string(dev_name, devlink_dev_name(devlink))
 		__string(driver_name, devlink_to_dev(devlink)->driver->name)
 		__field(int, err)
 		__string(msg, msg)
@@ -85,8 +85,8 @@ TRACE_EVENT(devlink_health_report,
 	TP_ARGS(devlink, reporter_name, msg),
 
 	TP_STRUCT__entry(
-		__string(bus_name, devlink_to_dev(devlink)->bus->name)
-		__string(dev_name, dev_name(devlink_to_dev(devlink)))
+		__string(bus_name, devlink_bus_name(devlink))
+		__string(dev_name, devlink_dev_name(devlink))
 		__string(driver_name, devlink_to_dev(devlink)->driver->name)
 		__string(reporter_name, reporter_name)
 		__string(msg, msg)
@@ -116,8 +116,8 @@ TRACE_EVENT(devlink_health_recover_aborted,
 	TP_ARGS(devlink, reporter_name, health_state, time_since_last_recover),
 
 	TP_STRUCT__entry(
-		__string(bus_name, devlink_to_dev(devlink)->bus->name)
-		__string(dev_name, dev_name(devlink_to_dev(devlink)))
+		__string(bus_name, devlink_bus_name(devlink))
+		__string(dev_name, devlink_dev_name(devlink))
 		__string(driver_name, devlink_to_dev(devlink)->driver->name)
 		__string(reporter_name, reporter_name)
 		__field(bool, health_state)
@@ -150,8 +150,8 @@ TRACE_EVENT(devlink_health_reporter_state_update,
 	TP_ARGS(devlink, reporter_name, new_state),
 
 	TP_STRUCT__entry(
-		__string(bus_name, devlink_to_dev(devlink)->bus->name)
-		__string(dev_name, dev_name(devlink_to_dev(devlink)))
+		__string(bus_name, devlink_bus_name(devlink))
+		__string(dev_name, devlink_dev_name(devlink))
 		__string(driver_name, devlink_to_dev(devlink)->driver->name)
 		__string(reporter_name, reporter_name)
 		__field(u8, new_state)
@@ -181,8 +181,8 @@ TRACE_EVENT(devlink_trap_report,
 	TP_ARGS(devlink, skb, metadata),
 
 	TP_STRUCT__entry(
-		__string(bus_name, devlink_to_dev(devlink)->bus->name)
-		__string(dev_name, dev_name(devlink_to_dev(devlink)))
+		__string(bus_name, devlink_bus_name(devlink))
+		__string(dev_name, devlink_dev_name(devlink))
 		__string(driver_name, devlink_to_dev(devlink)->driver->name)
 		__string(trap_name, metadata->trap_name)
 		__string(trap_group_name, metadata->trap_group_name)
diff --git a/net/devlink/core.c b/net/devlink/core.c
index d8e509a669bf..63709c132a7c 100644
--- a/net/devlink/core.c
+++ b/net/devlink/core.c
@@ -248,6 +248,18 @@ struct device *devlink_to_dev(const struct devlink *devlink)
 }
 EXPORT_SYMBOL_GPL(devlink_to_dev);
 
+const char *devlink_bus_name(const struct devlink *devlink)
+{
+	return devlink->dev->bus->name;
+}
+EXPORT_SYMBOL_GPL(devlink_bus_name);
+
+const char *devlink_dev_name(const struct devlink *devlink)
+{
+	return dev_name(devlink->dev);
+}
+EXPORT_SYMBOL_GPL(devlink_dev_name);
+
 struct net *devlink_net(const struct devlink *devlink)
 {
 	return read_pnet(&devlink->_net);
diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index 31fa98af418e..1b770de0313e 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -174,9 +174,9 @@ devlink_dump_state(struct netlink_callback *cb)
 static inline int
 devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
 {
-	if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
+	if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink_bus_name(devlink)))
 		return -EMSGSIZE;
-	if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
+	if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, devlink_dev_name(devlink)))
 		return -EMSGSIZE;
 	if (nla_put_uint(msg, DEVLINK_ATTR_INDEX, devlink->index))
 		return -EMSGSIZE;
@@ -211,8 +211,8 @@ static inline void devlink_nl_obj_desc_init(struct devlink_obj_desc *desc,
 					    struct devlink *devlink)
 {
 	memset(desc, 0, sizeof(*desc));
-	desc->bus_name = devlink->dev->bus->name;
-	desc->dev_name = dev_name(devlink->dev);
+	desc->bus_name = devlink_bus_name(devlink);
+	desc->dev_name = devlink_dev_name(devlink);
 }
 
 static inline void devlink_nl_obj_desc_port_set(struct devlink_obj_desc *desc,
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
index 593605c1b1ef..56817b85a3f9 100644
--- a/net/devlink/netlink.c
+++ b/net/devlink/netlink.c
@@ -193,8 +193,8 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
 	devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
 
 	devlinks_xa_for_each_registered_get(net, index, devlink) {
-		if (strcmp(devlink->dev->bus->name, busname) == 0 &&
-		    strcmp(dev_name(devlink->dev), devname) == 0) {
+		if (strcmp(devlink_bus_name(devlink), busname) == 0 &&
+		    strcmp(devlink_dev_name(devlink), devname) == 0) {
 			devl_dev_lock(devlink, dev_lock);
 			if (devl_is_registered(devlink))
 				return devlink;
diff --git a/net/devlink/port.c b/net/devlink/port.c
index 1ff609571ea4..fa3e1597711b 100644
--- a/net/devlink/port.c
+++ b/net/devlink/port.c
@@ -220,8 +220,8 @@ size_t devlink_nl_port_handle_size(struct devlink_port *devlink_port)
 {
 	struct devlink *devlink = devlink_port->devlink;
 
-	return nla_total_size(strlen(devlink->dev->bus->name) + 1) /* DEVLINK_ATTR_BUS_NAME */
-	     + nla_total_size(strlen(dev_name(devlink->dev)) + 1) /* DEVLINK_ATTR_DEV_NAME */
+	return nla_total_size(strlen(devlink_bus_name(devlink)) + 1) /* DEVLINK_ATTR_BUS_NAME */
+	     + nla_total_size(strlen(devlink_dev_name(devlink)) + 1) /* DEVLINK_ATTR_DEV_NAME */
 	     + nla_total_size(8) /* DEVLINK_ATTR_INDEX */
 	     + nla_total_size(4); /* DEVLINK_ATTR_PORT_INDEX */
 }
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 03/13] devlink: avoid extra iterations when found devlink is not registered
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
  2026-03-12 10:03 ` [PATCH net-next v4 01/13] devlink: expose devlink instance index over netlink Jiri Pirko
  2026-03-12 10:03 ` [PATCH net-next v4 02/13] devlink: add helpers to get bus_name/dev_name Jiri Pirko
@ 2026-03-12 10:03 ` Jiri Pirko
  2026-03-12 10:03 ` [PATCH net-next v4 04/13] devlink: allow to use devlink index as a command handle Jiri Pirko
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Since the one found is not registered, very unlikely another one with
the same bus_name/dev_name is going to be found. Stop right away and
prepare common "found" path for the follow-up patch.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 net/devlink/netlink.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
index 56817b85a3f9..7b205f677b7a 100644
--- a/net/devlink/netlink.c
+++ b/net/devlink/netlink.c
@@ -194,16 +194,20 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
 
 	devlinks_xa_for_each_registered_get(net, index, devlink) {
 		if (strcmp(devlink_bus_name(devlink), busname) == 0 &&
-		    strcmp(devlink_dev_name(devlink), devname) == 0) {
-			devl_dev_lock(devlink, dev_lock);
-			if (devl_is_registered(devlink))
-				return devlink;
-			devl_dev_unlock(devlink, dev_lock);
-		}
+		    strcmp(devlink_dev_name(devlink), devname) == 0)
+			goto found;
 		devlink_put(devlink);
 	}
 
 	return ERR_PTR(-ENODEV);
+
+found:
+	devl_dev_lock(devlink, dev_lock);
+	if (devl_is_registered(devlink))
+		return devlink;
+	devl_dev_unlock(devlink, dev_lock);
+	devlink_put(devlink);
+	return ERR_PTR(-ENODEV);
 }
 
 static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info,
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 04/13] devlink: allow to use devlink index as a command handle
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (2 preceding siblings ...)
  2026-03-12 10:03 ` [PATCH net-next v4 03/13] devlink: avoid extra iterations when found devlink is not registered Jiri Pirko
@ 2026-03-12 10:03 ` Jiri Pirko
  2026-03-12 10:03 ` [PATCH net-next v4 05/13] devlink: support index-based lookup via bus_name/dev_name handle Jiri Pirko
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Currently devlink instances are addressed bus_name/dev_name tuple.
Allow the newly introduced DEVLINK_ATTR_INDEX to be used as
an alternative handle for all devlink commands.

When DEVLINK_ATTR_INDEX is present in the request, use it for a direct
xarray lookup instead of iterating over all instances comparing
bus_name/dev_name strings.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v3->v4:
- added checks-max-u32-max to yaml
- removed no longer necessary index max check
  from devlink_get_from_attrs_lock()
v2->v3:
- check out of bounds index
- reject mixture of handle approaches
---
 Documentation/netlink/specs/devlink.yaml |  53 ++++
 net/devlink/core.c                       |  16 +-
 net/devlink/devl_internal.h              |   1 +
 net/devlink/netlink.c                    |  14 +-
 net/devlink/netlink_gen.c                | 355 ++++++++++++++---------
 5 files changed, 296 insertions(+), 143 deletions(-)

diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml
index 1bed67a0eefb..b495d56b9137 100644
--- a/Documentation/netlink/specs/devlink.yaml
+++ b/Documentation/netlink/specs/devlink.yaml
@@ -871,6 +871,8 @@ attribute-sets:
         name: index
         type: uint
         doc: Unique devlink instance index.
+        checks:
+          max: u32-max
   -
     name: dl-dev-stats
     subset-of: devlink
@@ -1310,6 +1312,7 @@ operations:
           attributes: &dev-id-attrs
             - bus-name
             - dev-name
+            - index
         reply: &get-reply
           value: 3
           attributes:
@@ -1334,6 +1337,7 @@ operations:
           attributes: &port-id-attrs
             - bus-name
             - dev-name
+            - index
             - port-index
         reply:
           value: 7
@@ -1358,6 +1362,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
             - port-type
             - port-function
@@ -1375,6 +1380,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
             - port-flavour
             - port-pci-pf-number
@@ -1409,6 +1415,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
             - port-split-count
 
@@ -1437,6 +1444,7 @@ operations:
           attributes: &sb-id-attrs
             - bus-name
             - dev-name
+            - index
             - sb-index
         reply: &sb-get-reply
           value: 13
@@ -1459,6 +1467,7 @@ operations:
           attributes: &sb-pool-id-attrs
             - bus-name
             - dev-name
+            - index
             - sb-index
             - sb-pool-index
         reply: &sb-pool-get-reply
@@ -1482,6 +1491,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - sb-index
             - sb-pool-index
             - sb-pool-threshold-type
@@ -1500,6 +1510,7 @@ operations:
           attributes: &sb-port-pool-id-attrs
             - bus-name
             - dev-name
+            - index
             - port-index
             - sb-index
             - sb-pool-index
@@ -1524,6 +1535,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
             - sb-index
             - sb-pool-index
@@ -1542,6 +1554,7 @@ operations:
           attributes: &sb-tc-pool-bind-id-attrs
             - bus-name
             - dev-name
+            - index
             - port-index
             - sb-index
             - sb-pool-type
@@ -1567,6 +1580,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
             - sb-index
             - sb-pool-index
@@ -1588,6 +1602,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - sb-index
 
     -
@@ -1603,6 +1618,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - sb-index
 
     -
@@ -1621,6 +1637,7 @@ operations:
           attributes: &eswitch-attrs
             - bus-name
             - dev-name
+            - index
             - eswitch-mode
             - eswitch-inline-mode
             - eswitch-encap-mode
@@ -1649,12 +1666,14 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - dpipe-table-name
         reply:
           value: 31
           attributes:
             - bus-name
             - dev-name
+            - index
             - dpipe-tables
 
     -
@@ -1669,11 +1688,13 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - dpipe-table-name
         reply:
           attributes:
             - bus-name
             - dev-name
+            - index
             - dpipe-entries
 
     -
@@ -1688,10 +1709,12 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
         reply:
           attributes:
             - bus-name
             - dev-name
+            - index
             - dpipe-headers
 
     -
@@ -1707,6 +1730,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - dpipe-table-name
             - dpipe-table-counters-enabled
 
@@ -1723,6 +1747,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - resource-id
             - resource-size
 
@@ -1738,11 +1763,13 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
         reply:
           value: 36
           attributes:
             - bus-name
             - dev-name
+            - index
             - resource-list
 
     -
@@ -1758,6 +1785,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - reload-action
             - reload-limits
             - netns-pid
@@ -1767,6 +1795,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - reload-actions-performed
 
     -
@@ -1781,6 +1810,7 @@ operations:
           attributes: &param-id-attrs
             - bus-name
             - dev-name
+            - index
             - param-name
         reply: &param-get-reply
           attributes: *param-id-attrs
@@ -1802,6 +1832,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - param-name
             - param-type
             # param-value-data is missing here as the type is variable
@@ -1821,6 +1852,7 @@ operations:
           attributes: &region-id-attrs
             - bus-name
             - dev-name
+            - index
             - port-index
             - region-name
         reply: &region-get-reply
@@ -1845,6 +1877,7 @@ operations:
           attributes: &region-snapshot-id-attrs
             - bus-name
             - dev-name
+            - index
             - port-index
             - region-name
             - region-snapshot-id
@@ -1875,6 +1908,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
             - region-name
             - region-snapshot-id
@@ -1886,6 +1920,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
             - region-name
 
@@ -1935,6 +1970,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - info-driver-name
             - info-serial-number
             - info-version-fixed
@@ -1956,6 +1992,7 @@ operations:
           attributes: &health-reporter-id-attrs
             - bus-name
             - dev-name
+            - index
             - port-index
             - health-reporter-name
         reply: &health-reporter-get-reply
@@ -1978,6 +2015,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
             - health-reporter-name
             - health-reporter-graceful-period
@@ -2048,6 +2086,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - flash-update-file-name
             - flash-update-component
             - flash-update-overwrite-mask
@@ -2065,6 +2104,7 @@ operations:
           attributes: &trap-id-attrs
             - bus-name
             - dev-name
+            - index
             - trap-name
         reply: &trap-get-reply
           value: 63
@@ -2087,6 +2127,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - trap-name
             - trap-action
 
@@ -2103,6 +2144,7 @@ operations:
           attributes: &trap-group-id-attrs
             - bus-name
             - dev-name
+            - index
             - trap-group-name
         reply: &trap-group-get-reply
           value: 67
@@ -2125,6 +2167,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - trap-group-name
             - trap-action
             - trap-policer-id
@@ -2142,6 +2185,7 @@ operations:
           attributes: &trap-policer-id-attrs
             - bus-name
             - dev-name
+            - index
             - trap-policer-id
         reply: &trap-policer-get-reply
           value: 71
@@ -2164,6 +2208,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - trap-policer-id
             - trap-policer-rate
             - trap-policer-burst
@@ -2194,6 +2239,7 @@ operations:
           attributes: &rate-id-attrs
             - bus-name
             - dev-name
+            - index
             - port-index
             - rate-node-name
         reply: &rate-get-reply
@@ -2217,6 +2263,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - rate-node-name
             - rate-tx-share
             - rate-tx-max
@@ -2238,6 +2285,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - rate-node-name
             - rate-tx-share
             - rate-tx-max
@@ -2259,6 +2307,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - rate-node-name
 
     -
@@ -2274,6 +2323,7 @@ operations:
           attributes: &linecard-id-attrs
             - bus-name
             - dev-name
+            - index
             - linecard-index
         reply: &linecard-get-reply
           value: 80
@@ -2296,6 +2346,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - linecard-index
             - linecard-type
 
@@ -2329,6 +2380,7 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - selftests
 
     -
@@ -2340,4 +2392,5 @@ operations:
           attributes:
             - bus-name
             - dev-name
+            - index
             - port-index
diff --git a/net/devlink/core.c b/net/devlink/core.c
index 63709c132a7c..237558abcd63 100644
--- a/net/devlink/core.c
+++ b/net/devlink/core.c
@@ -333,13 +333,15 @@ void devlink_put(struct devlink *devlink)
 		queue_rcu_work(system_percpu_wq, &devlink->rwork);
 }
 
-struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp)
+static struct devlink *__devlinks_xa_find_get(struct net *net,
+					      unsigned long *indexp,
+					      unsigned long end)
 {
 	struct devlink *devlink = NULL;
 
 	rcu_read_lock();
 retry:
-	devlink = xa_find(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED);
+	devlink = xa_find(&devlinks, indexp, end, DEVLINK_REGISTERED);
 	if (!devlink)
 		goto unlock;
 
@@ -358,6 +360,16 @@ struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp)
 	goto retry;
 }
 
+struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp)
+{
+	return __devlinks_xa_find_get(net, indexp, ULONG_MAX);
+}
+
+struct devlink *devlinks_xa_lookup_get(struct net *net, unsigned long index)
+{
+	return __devlinks_xa_find_get(net, &index, index);
+}
+
 /**
  * devl_register - Register devlink instance
  * @devlink: devlink
diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index 1b770de0313e..395832ed4477 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -90,6 +90,7 @@ extern struct genl_family devlink_nl_family;
 	for (index = 0; (devlink = devlinks_xa_find_get(net, &index)); index++)
 
 struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp);
+struct devlink *devlinks_xa_lookup_get(struct net *net, unsigned long index);
 
 static inline bool __devl_is_registered(struct devlink *devlink)
 {
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
index 7b205f677b7a..9cba40285de4 100644
--- a/net/devlink/netlink.c
+++ b/net/devlink/netlink.c
@@ -186,6 +186,17 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
 	char *busname;
 	char *devname;
 
+	if (attrs[DEVLINK_ATTR_INDEX]) {
+		if (attrs[DEVLINK_ATTR_BUS_NAME] ||
+		    attrs[DEVLINK_ATTR_DEV_NAME])
+			return ERR_PTR(-EINVAL);
+		index = nla_get_u32(attrs[DEVLINK_ATTR_INDEX]);
+		devlink = devlinks_xa_lookup_get(net, index);
+		if (!devlink)
+			return ERR_PTR(-ENODEV);
+		goto found;
+	}
+
 	if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
 		return ERR_PTR(-EINVAL);
 
@@ -356,7 +367,8 @@ int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb,
 	int flags = NLM_F_MULTI;
 
 	if (attrs &&
-	    (attrs[DEVLINK_ATTR_BUS_NAME] || attrs[DEVLINK_ATTR_DEV_NAME]))
+	    (attrs[DEVLINK_ATTR_BUS_NAME] || attrs[DEVLINK_ATTR_DEV_NAME] ||
+	     attrs[DEVLINK_ATTR_INDEX]))
 		return devlink_nl_inst_single_dumpit(msg, cb, flags, dump_one,
 						     attrs);
 	else
diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c
index f4c61c2b4f22..eb35e80e01d1 100644
--- a/net/devlink/netlink_gen.c
+++ b/net/devlink/netlink_gen.c
@@ -11,6 +11,11 @@
 
 #include <uapi/linux/devlink.h>
 
+/* Integer value ranges */
+static const struct netlink_range_validation devlink_attr_index_range = {
+	.max	= U32_MAX,
+};
+
 /* Sparse enums validation callbacks */
 static int
 devlink_attr_param_type_validate(const struct nlattr *attr,
@@ -56,37 +61,42 @@ const struct nla_policy devlink_dl_selftest_id_nl_policy[DEVLINK_ATTR_SELFTEST_I
 };
 
 /* DEVLINK_CMD_GET - do */
-static const struct nla_policy devlink_get_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_PORT_GET - do */
-static const struct nla_policy devlink_port_get_do_nl_policy[DEVLINK_ATTR_PORT_INDEX + 1] = {
+static const struct nla_policy devlink_port_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_PORT_GET - dump */
-static const struct nla_policy devlink_port_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_port_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_PORT_SET - do */
-static const struct nla_policy devlink_port_set_nl_policy[DEVLINK_ATTR_PORT_FUNCTION + 1] = {
+static const struct nla_policy devlink_port_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_PORT_TYPE] = NLA_POLICY_MAX(NLA_U16, 3),
 	[DEVLINK_ATTR_PORT_FUNCTION] = NLA_POLICY_NESTED(devlink_dl_port_function_nl_policy),
 };
 
 /* DEVLINK_CMD_PORT_NEW - do */
-static const struct nla_policy devlink_port_new_nl_policy[DEVLINK_ATTR_PORT_PCI_SF_NUMBER + 1] = {
+static const struct nla_policy devlink_port_new_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_PORT_FLAVOUR] = NLA_POLICY_MAX(NLA_U16, 7),
 	[DEVLINK_ATTR_PORT_PCI_PF_NUMBER] = { .type = NLA_U16, },
@@ -95,58 +105,66 @@ static const struct nla_policy devlink_port_new_nl_policy[DEVLINK_ATTR_PORT_PCI_
 };
 
 /* DEVLINK_CMD_PORT_DEL - do */
-static const struct nla_policy devlink_port_del_nl_policy[DEVLINK_ATTR_PORT_INDEX + 1] = {
+static const struct nla_policy devlink_port_del_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_PORT_SPLIT - do */
-static const struct nla_policy devlink_port_split_nl_policy[DEVLINK_ATTR_PORT_SPLIT_COUNT + 1] = {
+static const struct nla_policy devlink_port_split_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_PORT_UNSPLIT - do */
-static const struct nla_policy devlink_port_unsplit_nl_policy[DEVLINK_ATTR_PORT_INDEX + 1] = {
+static const struct nla_policy devlink_port_unsplit_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_SB_GET - do */
-static const struct nla_policy devlink_sb_get_do_nl_policy[DEVLINK_ATTR_SB_INDEX + 1] = {
+static const struct nla_policy devlink_sb_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_SB_GET - dump */
-static const struct nla_policy devlink_sb_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_sb_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_SB_POOL_GET - do */
-static const struct nla_policy devlink_sb_pool_get_do_nl_policy[DEVLINK_ATTR_SB_POOL_INDEX + 1] = {
+static const struct nla_policy devlink_sb_pool_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16, },
 };
 
 /* DEVLINK_CMD_SB_POOL_GET - dump */
-static const struct nla_policy devlink_sb_pool_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_sb_pool_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_SB_POOL_SET - do */
-static const struct nla_policy devlink_sb_pool_set_nl_policy[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE + 1] = {
+static const struct nla_policy devlink_sb_pool_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16, },
 	[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = NLA_POLICY_MAX(NLA_U8, 1),
@@ -154,24 +172,27 @@ static const struct nla_policy devlink_sb_pool_set_nl_policy[DEVLINK_ATTR_SB_POO
 };
 
 /* DEVLINK_CMD_SB_PORT_POOL_GET - do */
-static const struct nla_policy devlink_sb_port_pool_get_do_nl_policy[DEVLINK_ATTR_SB_POOL_INDEX + 1] = {
+static const struct nla_policy devlink_sb_port_pool_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16, },
 };
 
 /* DEVLINK_CMD_SB_PORT_POOL_GET - dump */
-static const struct nla_policy devlink_sb_port_pool_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_sb_port_pool_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_SB_PORT_POOL_SET - do */
-static const struct nla_policy devlink_sb_port_pool_set_nl_policy[DEVLINK_ATTR_SB_THRESHOLD + 1] = {
+static const struct nla_policy devlink_sb_port_pool_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16, },
@@ -179,9 +200,10 @@ static const struct nla_policy devlink_sb_port_pool_set_nl_policy[DEVLINK_ATTR_S
 };
 
 /* DEVLINK_CMD_SB_TC_POOL_BIND_GET - do */
-static const struct nla_policy devlink_sb_tc_pool_bind_get_do_nl_policy[DEVLINK_ATTR_SB_TC_INDEX + 1] = {
+static const struct nla_policy devlink_sb_tc_pool_bind_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_POOL_TYPE] = NLA_POLICY_MAX(NLA_U8, 1),
@@ -189,15 +211,17 @@ static const struct nla_policy devlink_sb_tc_pool_bind_get_do_nl_policy[DEVLINK_
 };
 
 /* DEVLINK_CMD_SB_TC_POOL_BIND_GET - dump */
-static const struct nla_policy devlink_sb_tc_pool_bind_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_sb_tc_pool_bind_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_SB_TC_POOL_BIND_SET - do */
-static const struct nla_policy devlink_sb_tc_pool_bind_set_nl_policy[DEVLINK_ATTR_SB_TC_INDEX + 1] = {
+static const struct nla_policy devlink_sb_tc_pool_bind_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16, },
@@ -207,80 +231,91 @@ static const struct nla_policy devlink_sb_tc_pool_bind_set_nl_policy[DEVLINK_ATT
 };
 
 /* DEVLINK_CMD_SB_OCC_SNAPSHOT - do */
-static const struct nla_policy devlink_sb_occ_snapshot_nl_policy[DEVLINK_ATTR_SB_INDEX + 1] = {
+static const struct nla_policy devlink_sb_occ_snapshot_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_SB_OCC_MAX_CLEAR - do */
-static const struct nla_policy devlink_sb_occ_max_clear_nl_policy[DEVLINK_ATTR_SB_INDEX + 1] = {
+static const struct nla_policy devlink_sb_occ_max_clear_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_ESWITCH_GET - do */
-static const struct nla_policy devlink_eswitch_get_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_eswitch_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_ESWITCH_SET - do */
-static const struct nla_policy devlink_eswitch_set_nl_policy[DEVLINK_ATTR_ESWITCH_ENCAP_MODE + 1] = {
+static const struct nla_policy devlink_eswitch_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_ESWITCH_MODE] = NLA_POLICY_MAX(NLA_U16, 2),
 	[DEVLINK_ATTR_ESWITCH_INLINE_MODE] = NLA_POLICY_MAX(NLA_U8, 3),
 	[DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = NLA_POLICY_MAX(NLA_U8, 1),
 };
 
 /* DEVLINK_CMD_DPIPE_TABLE_GET - do */
-static const struct nla_policy devlink_dpipe_table_get_nl_policy[DEVLINK_ATTR_DPIPE_TABLE_NAME + 1] = {
+static const struct nla_policy devlink_dpipe_table_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_DPIPE_ENTRIES_GET - do */
-static const struct nla_policy devlink_dpipe_entries_get_nl_policy[DEVLINK_ATTR_DPIPE_TABLE_NAME + 1] = {
+static const struct nla_policy devlink_dpipe_entries_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_DPIPE_HEADERS_GET - do */
-static const struct nla_policy devlink_dpipe_headers_get_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_dpipe_headers_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET - do */
-static const struct nla_policy devlink_dpipe_table_counters_set_nl_policy[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED + 1] = {
+static const struct nla_policy devlink_dpipe_table_counters_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8, },
 };
 
 /* DEVLINK_CMD_RESOURCE_SET - do */
-static const struct nla_policy devlink_resource_set_nl_policy[DEVLINK_ATTR_RESOURCE_SIZE + 1] = {
+static const struct nla_policy devlink_resource_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64, },
 	[DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64, },
 };
 
 /* DEVLINK_CMD_RESOURCE_DUMP - do */
-static const struct nla_policy devlink_resource_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_resource_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_RELOAD - do */
-static const struct nla_policy devlink_reload_nl_policy[DEVLINK_ATTR_RELOAD_LIMITS + 1] = {
+static const struct nla_policy devlink_reload_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, 1, 2),
 	[DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(6),
 	[DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32, },
@@ -289,22 +324,25 @@ static const struct nla_policy devlink_reload_nl_policy[DEVLINK_ATTR_RELOAD_LIMI
 };
 
 /* DEVLINK_CMD_PARAM_GET - do */
-static const struct nla_policy devlink_param_get_do_nl_policy[DEVLINK_ATTR_PARAM_NAME + 1] = {
+static const struct nla_policy devlink_param_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_PARAM_GET - dump */
-static const struct nla_policy devlink_param_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_param_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_PARAM_SET - do */
-static const struct nla_policy devlink_param_set_nl_policy[DEVLINK_ATTR_PARAM_RESET_DEFAULT + 1] = {
+static const struct nla_policy devlink_param_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_PARAM_TYPE] = NLA_POLICY_VALIDATE_FN(NLA_U8, &devlink_attr_param_type_validate),
 	[DEVLINK_ATTR_PARAM_VALUE_CMODE] = NLA_POLICY_MAX(NLA_U8, 2),
@@ -312,41 +350,46 @@ static const struct nla_policy devlink_param_set_nl_policy[DEVLINK_ATTR_PARAM_RE
 };
 
 /* DEVLINK_CMD_REGION_GET - do */
-static const struct nla_policy devlink_region_get_do_nl_policy[DEVLINK_ATTR_REGION_NAME + 1] = {
+static const struct nla_policy devlink_region_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_REGION_GET - dump */
-static const struct nla_policy devlink_region_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_region_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_REGION_NEW - do */
-static const struct nla_policy devlink_region_new_nl_policy[DEVLINK_ATTR_REGION_SNAPSHOT_ID + 1] = {
+static const struct nla_policy devlink_region_new_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_REGION_DEL - do */
-static const struct nla_policy devlink_region_del_nl_policy[DEVLINK_ATTR_REGION_SNAPSHOT_ID + 1] = {
+static const struct nla_policy devlink_region_del_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_REGION_READ - dump */
-static const struct nla_policy devlink_region_read_nl_policy[DEVLINK_ATTR_REGION_DIRECT + 1] = {
+static const struct nla_policy devlink_region_read_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32, },
@@ -356,44 +399,50 @@ static const struct nla_policy devlink_region_read_nl_policy[DEVLINK_ATTR_REGION
 };
 
 /* DEVLINK_CMD_PORT_PARAM_GET - do */
-static const struct nla_policy devlink_port_param_get_nl_policy[DEVLINK_ATTR_PORT_INDEX + 1] = {
+static const struct nla_policy devlink_port_param_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_PORT_PARAM_SET - do */
-static const struct nla_policy devlink_port_param_set_nl_policy[DEVLINK_ATTR_PORT_INDEX + 1] = {
+static const struct nla_policy devlink_port_param_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_INFO_GET - do */
-static const struct nla_policy devlink_info_get_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_info_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_HEALTH_REPORTER_GET - do */
-static const struct nla_policy devlink_health_reporter_get_do_nl_policy[DEVLINK_ATTR_HEALTH_REPORTER_NAME + 1] = {
+static const struct nla_policy devlink_health_reporter_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_HEALTH_REPORTER_GET - dump */
-static const struct nla_policy devlink_health_reporter_get_dump_nl_policy[DEVLINK_ATTR_PORT_INDEX + 1] = {
+static const struct nla_policy devlink_health_reporter_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_HEALTH_REPORTER_SET - do */
-static const struct nla_policy devlink_health_reporter_set_nl_policy[DEVLINK_ATTR_HEALTH_REPORTER_BURST_PERIOD + 1] = {
+static const struct nla_policy devlink_health_reporter_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64, },
@@ -403,137 +452,155 @@ static const struct nla_policy devlink_health_reporter_set_nl_policy[DEVLINK_ATT
 };
 
 /* DEVLINK_CMD_HEALTH_REPORTER_RECOVER - do */
-static const struct nla_policy devlink_health_reporter_recover_nl_policy[DEVLINK_ATTR_HEALTH_REPORTER_NAME + 1] = {
+static const struct nla_policy devlink_health_reporter_recover_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE - do */
-static const struct nla_policy devlink_health_reporter_diagnose_nl_policy[DEVLINK_ATTR_HEALTH_REPORTER_NAME + 1] = {
+static const struct nla_policy devlink_health_reporter_diagnose_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET - dump */
-static const struct nla_policy devlink_health_reporter_dump_get_nl_policy[DEVLINK_ATTR_HEALTH_REPORTER_NAME + 1] = {
+static const struct nla_policy devlink_health_reporter_dump_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR - do */
-static const struct nla_policy devlink_health_reporter_dump_clear_nl_policy[DEVLINK_ATTR_HEALTH_REPORTER_NAME + 1] = {
+static const struct nla_policy devlink_health_reporter_dump_clear_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_FLASH_UPDATE - do */
-static const struct nla_policy devlink_flash_update_nl_policy[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK + 1] = {
+static const struct nla_policy devlink_flash_update_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK] = NLA_POLICY_BITFIELD32(3),
 };
 
 /* DEVLINK_CMD_TRAP_GET - do */
-static const struct nla_policy devlink_trap_get_do_nl_policy[DEVLINK_ATTR_TRAP_NAME + 1] = {
+static const struct nla_policy devlink_trap_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_TRAP_GET - dump */
-static const struct nla_policy devlink_trap_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_trap_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_TRAP_SET - do */
-static const struct nla_policy devlink_trap_set_nl_policy[DEVLINK_ATTR_TRAP_ACTION + 1] = {
+static const struct nla_policy devlink_trap_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_TRAP_ACTION] = NLA_POLICY_MAX(NLA_U8, 2),
 };
 
 /* DEVLINK_CMD_TRAP_GROUP_GET - do */
-static const struct nla_policy devlink_trap_group_get_do_nl_policy[DEVLINK_ATTR_TRAP_GROUP_NAME + 1] = {
+static const struct nla_policy devlink_trap_group_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_TRAP_GROUP_GET - dump */
-static const struct nla_policy devlink_trap_group_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_trap_group_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_TRAP_GROUP_SET - do */
-static const struct nla_policy devlink_trap_group_set_nl_policy[DEVLINK_ATTR_TRAP_POLICER_ID + 1] = {
+static const struct nla_policy devlink_trap_group_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_TRAP_ACTION] = NLA_POLICY_MAX(NLA_U8, 2),
 	[DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_TRAP_POLICER_GET - do */
-static const struct nla_policy devlink_trap_policer_get_do_nl_policy[DEVLINK_ATTR_TRAP_POLICER_ID + 1] = {
+static const struct nla_policy devlink_trap_policer_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_TRAP_POLICER_GET - dump */
-static const struct nla_policy devlink_trap_policer_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_trap_policer_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_TRAP_POLICER_SET - do */
-static const struct nla_policy devlink_trap_policer_set_nl_policy[DEVLINK_ATTR_TRAP_POLICER_BURST + 1] = {
+static const struct nla_policy devlink_trap_policer_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64, },
 	[DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64, },
 };
 
 /* DEVLINK_CMD_HEALTH_REPORTER_TEST - do */
-static const struct nla_policy devlink_health_reporter_test_nl_policy[DEVLINK_ATTR_HEALTH_REPORTER_NAME + 1] = {
+static const struct nla_policy devlink_health_reporter_test_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_RATE_GET - do */
-static const struct nla_policy devlink_rate_get_do_nl_policy[DEVLINK_ATTR_RATE_NODE_NAME + 1] = {
+static const struct nla_policy devlink_rate_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_RATE_GET - dump */
-static const struct nla_policy devlink_rate_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_rate_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_RATE_SET - do */
-static const struct nla_policy devlink_rate_set_nl_policy[DEVLINK_ATTR_RATE_TC_BWS + 1] = {
+static const struct nla_policy devlink_rate_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_RATE_TX_SHARE] = { .type = NLA_U64, },
 	[DEVLINK_ATTR_RATE_TX_MAX] = { .type = NLA_U64, },
@@ -544,9 +611,10 @@ static const struct nla_policy devlink_rate_set_nl_policy[DEVLINK_ATTR_RATE_TC_B
 };
 
 /* DEVLINK_CMD_RATE_NEW - do */
-static const struct nla_policy devlink_rate_new_nl_policy[DEVLINK_ATTR_RATE_TC_BWS + 1] = {
+static const struct nla_policy devlink_rate_new_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_RATE_TX_SHARE] = { .type = NLA_U64, },
 	[DEVLINK_ATTR_RATE_TX_MAX] = { .type = NLA_U64, },
@@ -557,50 +625,57 @@ static const struct nla_policy devlink_rate_new_nl_policy[DEVLINK_ATTR_RATE_TC_B
 };
 
 /* DEVLINK_CMD_RATE_DEL - do */
-static const struct nla_policy devlink_rate_del_nl_policy[DEVLINK_ATTR_RATE_NODE_NAME + 1] = {
+static const struct nla_policy devlink_rate_del_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_LINECARD_GET - do */
-static const struct nla_policy devlink_linecard_get_do_nl_policy[DEVLINK_ATTR_LINECARD_INDEX + 1] = {
+static const struct nla_policy devlink_linecard_get_do_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32, },
 };
 
 /* DEVLINK_CMD_LINECARD_GET - dump */
-static const struct nla_policy devlink_linecard_get_dump_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_linecard_get_dump_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_LINECARD_SET - do */
-static const struct nla_policy devlink_linecard_set_nl_policy[DEVLINK_ATTR_LINECARD_TYPE + 1] = {
+static const struct nla_policy devlink_linecard_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32, },
 	[DEVLINK_ATTR_LINECARD_TYPE] = { .type = NLA_NUL_STRING, },
 };
 
 /* DEVLINK_CMD_SELFTESTS_GET - do */
-static const struct nla_policy devlink_selftests_get_nl_policy[DEVLINK_ATTR_DEV_NAME + 1] = {
+static const struct nla_policy devlink_selftests_get_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 };
 
 /* DEVLINK_CMD_SELFTESTS_RUN - do */
-static const struct nla_policy devlink_selftests_run_nl_policy[DEVLINK_ATTR_SELFTESTS + 1] = {
+static const struct nla_policy devlink_selftests_run_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_SELFTESTS] = NLA_POLICY_NESTED(devlink_dl_selftest_id_nl_policy),
 };
 
 /* DEVLINK_CMD_NOTIFY_FILTER_SET - do */
-static const struct nla_policy devlink_notify_filter_set_nl_policy[DEVLINK_ATTR_PORT_INDEX + 1] = {
+static const struct nla_policy devlink_notify_filter_set_nl_policy[DEVLINK_ATTR_INDEX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range),
 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, },
 };
 
@@ -613,7 +688,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
@@ -629,14 +704,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_port_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_port_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_PORT_GET,
 		.dumpit		= devlink_nl_port_get_dumpit,
 		.policy		= devlink_port_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -646,7 +721,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_port_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_port_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_FUNCTION,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -656,7 +731,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_port_new_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_port_new_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_PCI_SF_NUMBER,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -666,7 +741,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_port_del_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_port_del_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -676,7 +751,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_port_split_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_port_split_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_SPLIT_COUNT,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -686,7 +761,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_port_unsplit_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_port_unsplit_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -696,14 +771,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_SB_GET,
 		.dumpit		= devlink_nl_sb_get_dumpit,
 		.policy		= devlink_sb_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -713,14 +788,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_pool_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_pool_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_POOL_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_SB_POOL_GET,
 		.dumpit		= devlink_nl_sb_pool_get_dumpit,
 		.policy		= devlink_sb_pool_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -730,7 +805,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_pool_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_pool_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -740,14 +815,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_port_pool_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_port_pool_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_POOL_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_SB_PORT_POOL_GET,
 		.dumpit		= devlink_nl_sb_port_pool_get_dumpit,
 		.policy		= devlink_sb_port_pool_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -757,7 +832,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_port_pool_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_port_pool_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_THRESHOLD,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -767,14 +842,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_tc_pool_bind_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_tc_pool_bind_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_TC_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_SB_TC_POOL_BIND_GET,
 		.dumpit		= devlink_nl_sb_tc_pool_bind_get_dumpit,
 		.policy		= devlink_sb_tc_pool_bind_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -784,7 +859,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_tc_pool_bind_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_tc_pool_bind_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_TC_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -794,7 +869,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_occ_snapshot_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_occ_snapshot_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -804,7 +879,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_sb_occ_max_clear_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_sb_occ_max_clear_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SB_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -814,7 +889,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_eswitch_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_eswitch_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -824,7 +899,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_eswitch_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_eswitch_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_ESWITCH_ENCAP_MODE,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -834,7 +909,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_dpipe_table_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_dpipe_table_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DPIPE_TABLE_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
@@ -844,7 +919,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_dpipe_entries_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_dpipe_entries_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DPIPE_TABLE_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
@@ -854,7 +929,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_dpipe_headers_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_dpipe_headers_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
@@ -864,7 +939,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_dpipe_table_counters_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_dpipe_table_counters_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -874,7 +949,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_resource_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_resource_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_RESOURCE_SIZE,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -884,7 +959,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_resource_dump_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_resource_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
@@ -894,7 +969,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_reload_doit,
 		.post_doit	= devlink_nl_post_doit_dev_lock,
 		.policy		= devlink_reload_nl_policy,
-		.maxattr	= DEVLINK_ATTR_RELOAD_LIMITS,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -904,14 +979,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_param_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_param_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PARAM_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_PARAM_GET,
 		.dumpit		= devlink_nl_param_get_dumpit,
 		.policy		= devlink_param_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -921,7 +996,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_param_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_param_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PARAM_RESET_DEFAULT,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -931,14 +1006,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_region_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_region_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_REGION_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_REGION_GET,
 		.dumpit		= devlink_nl_region_get_dumpit,
 		.policy		= devlink_region_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -948,7 +1023,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_region_new_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_region_new_nl_policy,
-		.maxattr	= DEVLINK_ATTR_REGION_SNAPSHOT_ID,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -958,7 +1033,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_region_del_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_region_del_nl_policy,
-		.maxattr	= DEVLINK_ATTR_REGION_SNAPSHOT_ID,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -966,7 +1041,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.validate	= GENL_DONT_VALIDATE_DUMP_STRICT,
 		.dumpit		= devlink_nl_region_read_dumpit,
 		.policy		= devlink_region_read_nl_policy,
-		.maxattr	= DEVLINK_ATTR_REGION_DIRECT,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -976,7 +1051,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_port_param_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_port_param_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
@@ -992,7 +1067,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_port_param_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_port_param_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1002,7 +1077,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_info_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_info_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
@@ -1018,14 +1093,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_health_reporter_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_health_reporter_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_HEALTH_REPORTER_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_HEALTH_REPORTER_GET,
 		.dumpit		= devlink_nl_health_reporter_get_dumpit,
 		.policy		= devlink_health_reporter_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -1035,7 +1110,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_health_reporter_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_health_reporter_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_HEALTH_REPORTER_BURST_PERIOD,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1045,7 +1120,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_health_reporter_recover_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_health_reporter_recover_nl_policy,
-		.maxattr	= DEVLINK_ATTR_HEALTH_REPORTER_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1055,7 +1130,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_health_reporter_diagnose_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_health_reporter_diagnose_nl_policy,
-		.maxattr	= DEVLINK_ATTR_HEALTH_REPORTER_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1063,7 +1138,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.validate	= GENL_DONT_VALIDATE_DUMP_STRICT,
 		.dumpit		= devlink_nl_health_reporter_dump_get_dumpit,
 		.policy		= devlink_health_reporter_dump_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_HEALTH_REPORTER_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -1073,7 +1148,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_health_reporter_dump_clear_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_health_reporter_dump_clear_nl_policy,
-		.maxattr	= DEVLINK_ATTR_HEALTH_REPORTER_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1083,7 +1158,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_flash_update_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_flash_update_nl_policy,
-		.maxattr	= DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1093,14 +1168,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_trap_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_trap_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_TRAP_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_TRAP_GET,
 		.dumpit		= devlink_nl_trap_get_dumpit,
 		.policy		= devlink_trap_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -1110,7 +1185,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_trap_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_trap_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_TRAP_ACTION,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1120,14 +1195,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_trap_group_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_trap_group_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_TRAP_GROUP_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_TRAP_GROUP_GET,
 		.dumpit		= devlink_nl_trap_group_get_dumpit,
 		.policy		= devlink_trap_group_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -1137,7 +1212,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_trap_group_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_trap_group_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_TRAP_POLICER_ID,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1147,14 +1222,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_trap_policer_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_trap_policer_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_TRAP_POLICER_ID,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_TRAP_POLICER_GET,
 		.dumpit		= devlink_nl_trap_policer_get_dumpit,
 		.policy		= devlink_trap_policer_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -1164,7 +1239,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_trap_policer_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_trap_policer_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_TRAP_POLICER_BURST,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1174,7 +1249,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_health_reporter_test_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_health_reporter_test_nl_policy,
-		.maxattr	= DEVLINK_ATTR_HEALTH_REPORTER_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1184,14 +1259,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_rate_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_rate_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_RATE_NODE_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_RATE_GET,
 		.dumpit		= devlink_nl_rate_get_dumpit,
 		.policy		= devlink_rate_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -1201,7 +1276,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_rate_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_rate_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_RATE_TC_BWS,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1211,7 +1286,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_rate_new_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_rate_new_nl_policy,
-		.maxattr	= DEVLINK_ATTR_RATE_TC_BWS,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1221,7 +1296,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_rate_del_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_rate_del_nl_policy,
-		.maxattr	= DEVLINK_ATTR_RATE_NODE_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1231,14 +1306,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_linecard_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_linecard_get_do_nl_policy,
-		.maxattr	= DEVLINK_ATTR_LINECARD_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_LINECARD_GET,
 		.dumpit		= devlink_nl_linecard_get_dumpit,
 		.policy		= devlink_linecard_get_dump_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
 	{
@@ -1248,7 +1323,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_linecard_set_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_linecard_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_LINECARD_TYPE,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
@@ -1258,7 +1333,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_selftests_get_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_selftests_get_nl_policy,
-		.maxattr	= DEVLINK_ATTR_DEV_NAME,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 	{
@@ -1274,14 +1349,14 @@ const struct genl_split_ops devlink_nl_ops[74] = {
 		.doit		= devlink_nl_selftests_run_doit,
 		.post_doit	= devlink_nl_post_doit,
 		.policy		= devlink_selftests_run_nl_policy,
-		.maxattr	= DEVLINK_ATTR_SELFTESTS,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
 	},
 	{
 		.cmd		= DEVLINK_CMD_NOTIFY_FILTER_SET,
 		.doit		= devlink_nl_notify_filter_set_doit,
 		.policy		= devlink_notify_filter_set_nl_policy,
-		.maxattr	= DEVLINK_ATTR_PORT_INDEX,
+		.maxattr	= DEVLINK_ATTR_INDEX,
 		.flags		= GENL_CMD_CAP_DO,
 	},
 };
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 05/13] devlink: support index-based lookup via bus_name/dev_name handle
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (3 preceding siblings ...)
  2026-03-12 10:03 ` [PATCH net-next v4 04/13] devlink: allow to use devlink index as a command handle Jiri Pirko
@ 2026-03-12 10:03 ` Jiri Pirko
  2026-03-12 10:04 ` [PATCH net-next v4 06/13] devlink: support index-based notification filtering Jiri Pirko
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:03 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Devlink instances without a backing device use bus_name
"devlink_index" and dev_name set to the decimal index string.
When user space sends this handle, detect the pattern and perform
a direct xarray lookup by index instead of iterating all instances.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v2->v3:
- unify return value -ENODEV even in case non-numeric dev_name
v1->v2:
- moved DEVLINK_INDEX_BUS_NAME definition here from patch #7
---
 include/uapi/linux/devlink.h | 2 ++
 net/devlink/netlink.c        | 9 +++++++++
 2 files changed, 11 insertions(+)

diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 1ba3436db4ae..7de2d8cc862f 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -19,6 +19,8 @@
 #define DEVLINK_GENL_VERSION 0x1
 #define DEVLINK_GENL_MCGRP_CONFIG_NAME "config"
 
+#define DEVLINK_INDEX_BUS_NAME "devlink_index"
+
 enum devlink_command {
 	/* don't change the order or add anything between, this is ABI! */
 	DEVLINK_CMD_UNSPEC,
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
index 9cba40285de4..fa38fca22fe4 100644
--- a/net/devlink/netlink.c
+++ b/net/devlink/netlink.c
@@ -203,6 +203,15 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
 	busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
 	devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
 
+	if (!strcmp(busname, DEVLINK_INDEX_BUS_NAME)) {
+		if (kstrtoul(devname, 10, &index))
+			return ERR_PTR(-ENODEV);
+		devlink = devlinks_xa_lookup_get(net, index);
+		if (!devlink)
+			return ERR_PTR(-ENODEV);
+		goto found;
+	}
+
 	devlinks_xa_for_each_registered_get(net, index, devlink) {
 		if (strcmp(devlink_bus_name(devlink), busname) == 0 &&
 		    strcmp(devlink_dev_name(devlink), devname) == 0)
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 06/13] devlink: support index-based notification filtering
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (4 preceding siblings ...)
  2026-03-12 10:03 ` [PATCH net-next v4 05/13] devlink: support index-based lookup via bus_name/dev_name handle Jiri Pirko
@ 2026-03-12 10:04 ` Jiri Pirko
  2026-03-12 10:04 ` [PATCH net-next v4 07/13] devlink: introduce __devlink_alloc() with dev driver pointer Jiri Pirko
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Extend the notification filter descriptor with devlink_index so
that userspace can filter notifications by devlink instance index
in addition to bus_name/dev_name.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v2->v3:
- new patch
---
 net/devlink/devl_internal.h |  4 ++++
 net/devlink/netlink.c       | 11 ++++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index 395832ed4477..f0ebfb936770 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -205,6 +205,8 @@ struct devlink_obj_desc {
 	const char *dev_name;
 	unsigned int port_index;
 	bool port_index_valid;
+	unsigned int devlink_index;
+	bool devlink_index_valid;
 	long data[];
 };
 
@@ -214,6 +216,8 @@ static inline void devlink_nl_obj_desc_init(struct devlink_obj_desc *desc,
 	memset(desc, 0, sizeof(*desc));
 	desc->bus_name = devlink_bus_name(devlink);
 	desc->dev_name = devlink_dev_name(devlink);
+	desc->devlink_index = devlink->index;
+	desc->devlink_index_valid = true;
 }
 
 static inline void devlink_nl_obj_desc_port_set(struct devlink_obj_desc *desc,
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
index fa38fca22fe4..32ddbe244cb7 100644
--- a/net/devlink/netlink.c
+++ b/net/devlink/netlink.c
@@ -73,13 +73,19 @@ int devlink_nl_notify_filter_set_doit(struct sk_buff *skb,
 		flt->dev_name = pos;
 	}
 
+	if (attrs[DEVLINK_ATTR_INDEX]) {
+		flt->devlink_index = nla_get_uint(attrs[DEVLINK_ATTR_INDEX]);
+		flt->devlink_index_valid = true;
+	}
+
 	if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
 		flt->port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
 		flt->port_index_valid = true;
 	}
 
 	/* Don't attach empty filter. */
-	if (!flt->bus_name && !flt->dev_name && !flt->port_index_valid) {
+	if (!flt->bus_name && !flt->dev_name &&
+	    !flt->devlink_index_valid && !flt->port_index_valid) {
 		kfree(flt);
 		flt = NULL;
 	}
@@ -100,6 +106,9 @@ int devlink_nl_notify_filter_set_doit(struct sk_buff *skb,
 static bool devlink_obj_desc_match(const struct devlink_obj_desc *desc,
 				   const struct devlink_obj_desc *flt)
 {
+	if (desc->devlink_index_valid && flt->devlink_index_valid &&
+	    desc->devlink_index != flt->devlink_index)
+		return false;
 	if (desc->bus_name && flt->bus_name &&
 	    strcmp(desc->bus_name, flt->bus_name))
 		return false;
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 07/13] devlink: introduce __devlink_alloc() with dev driver pointer
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (5 preceding siblings ...)
  2026-03-12 10:04 ` [PATCH net-next v4 06/13] devlink: support index-based notification filtering Jiri Pirko
@ 2026-03-12 10:04 ` Jiri Pirko
  2026-03-12 10:04 ` [PATCH net-next v4 08/13] devlink: add devlink_dev_driver_name() helper and use it in trace events Jiri Pirko
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Introduce __devlink_alloc() as an internal devlink allocator that
accepts a struct device_driver pointer and stores it in the devlink
instance. This allows internal devlink code (e.g. shared instances)
to associate a driver with a devlink instance without need to pass dev
pointer.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v2->v3:
- new patch
---
 net/devlink/core.c          | 40 ++++++++++++++++++++++---------------
 net/devlink/devl_internal.h |  5 +++++
 2 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/net/devlink/core.c b/net/devlink/core.c
index 237558abcd63..fcb73d3e56aa 100644
--- a/net/devlink/core.c
+++ b/net/devlink/core.c
@@ -418,27 +418,15 @@ void devlink_unregister(struct devlink *devlink)
 }
 EXPORT_SYMBOL_GPL(devlink_unregister);
 
-/**
- *	devlink_alloc_ns - Allocate new devlink instance resources
- *	in specific namespace
- *
- *	@ops: ops
- *	@priv_size: size of user private data
- *	@net: net namespace
- *	@dev: parent device
- *
- *	Allocate new devlink instance resources, including devlink index
- *	and name.
- */
-struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
-				 size_t priv_size, struct net *net,
-				 struct device *dev)
+struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size,
+				struct net *net, struct device *dev,
+				const struct device_driver *dev_driver)
 {
 	struct devlink *devlink;
 	static u32 last_id;
 	int ret;
 
-	WARN_ON(!ops || !dev);
+	WARN_ON(!ops || !dev || !dev_driver);
 	if (!devlink_reload_actions_valid(ops))
 		return NULL;
 
@@ -453,6 +441,7 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
 
 	devlink->dev = get_device(dev);
 	devlink->ops = ops;
+	devlink->dev_driver = dev_driver;
 	xa_init_flags(&devlink->ports, XA_FLAGS_ALLOC);
 	xa_init_flags(&devlink->params, XA_FLAGS_ALLOC);
 	xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC);
@@ -480,6 +469,25 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
 	kvfree(devlink);
 	return NULL;
 }
+
+/**
+ *	devlink_alloc_ns - Allocate new devlink instance resources
+ *	in specific namespace
+ *
+ *	@ops: ops
+ *	@priv_size: size of user private data
+ *	@net: net namespace
+ *	@dev: parent device
+ *
+ *	Allocate new devlink instance resources, including devlink index
+ *	and name.
+ */
+struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
+				 size_t priv_size, struct net *net,
+				 struct device *dev)
+{
+	return __devlink_alloc(ops, priv_size, net, dev, dev->driver);
+}
 EXPORT_SYMBOL_GPL(devlink_alloc_ns);
 
 /**
diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index f0ebfb936770..3cc7e696e0fd 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -49,6 +49,7 @@ struct devlink {
 	struct xarray snapshot_ids;
 	struct devlink_dev_stats stats;
 	struct device *dev;
+	const struct device_driver *dev_driver;
 	possible_net_t _net;
 	/* Serializes access to devlink instance specific objects such as
 	 * port, sb, dpipe, resource, params, region, traps and more.
@@ -66,6 +67,10 @@ struct devlink {
 extern struct xarray devlinks;
 extern struct genl_family devlink_nl_family;
 
+struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size,
+				struct net *net, struct device *dev,
+				const struct device_driver *dev_driver);
+
 /* devlink instances are open to the access from the user space after
  * devlink_register() call. Such logical barrier allows us to have certain
  * expectations related to locking.
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 08/13] devlink: add devlink_dev_driver_name() helper and use it in trace events
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (6 preceding siblings ...)
  2026-03-12 10:04 ` [PATCH net-next v4 07/13] devlink: introduce __devlink_alloc() with dev driver pointer Jiri Pirko
@ 2026-03-12 10:04 ` Jiri Pirko
  2026-03-12 10:04 ` [PATCH net-next v4 09/13] devlink: add devl_warn() helper and use it in port warnings Jiri Pirko
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

In preparation to dev-less devlinks, add devlink_dev_driver_name()
that returns the driver name stored in devlink struct, and use it in
all trace events.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v2->v3:
- using stored devlink->dev_driver
v1->v2:
- added missing symbol export
---
 include/net/devlink.h          |  1 +
 include/trace/events/devlink.h | 12 ++++++------
 net/devlink/core.c             |  6 ++++++
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index 0afb0958b910..45dec7067a8e 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -1613,6 +1613,7 @@ struct devlink *priv_to_devlink(void *priv);
 struct device *devlink_to_dev(const struct devlink *devlink);
 const char *devlink_bus_name(const struct devlink *devlink);
 const char *devlink_dev_name(const struct devlink *devlink);
+const char *devlink_dev_driver_name(const struct devlink *devlink);
 
 /* Devlink instance explicit locking */
 void devl_lock(struct devlink *devlink);
diff --git a/include/trace/events/devlink.h b/include/trace/events/devlink.h
index 32304ce9ad15..4f8edf77dfbe 100644
--- a/include/trace/events/devlink.h
+++ b/include/trace/events/devlink.h
@@ -23,7 +23,7 @@ TRACE_EVENT(devlink_hwmsg,
 	TP_STRUCT__entry(
 		__string(bus_name, devlink_bus_name(devlink))
 		__string(dev_name, devlink_dev_name(devlink))
-		__string(driver_name, devlink_to_dev(devlink)->driver->name)
+		__string(driver_name, devlink_dev_driver_name(devlink))
 		__field(bool, incoming)
 		__field(unsigned long, type)
 		__dynamic_array(u8, buf, len)
@@ -57,7 +57,7 @@ TRACE_EVENT(devlink_hwerr,
 	TP_STRUCT__entry(
 		__string(bus_name, devlink_bus_name(devlink))
 		__string(dev_name, devlink_dev_name(devlink))
-		__string(driver_name, devlink_to_dev(devlink)->driver->name)
+		__string(driver_name, devlink_dev_driver_name(devlink))
 		__field(int, err)
 		__string(msg, msg)
 		),
@@ -87,7 +87,7 @@ TRACE_EVENT(devlink_health_report,
 	TP_STRUCT__entry(
 		__string(bus_name, devlink_bus_name(devlink))
 		__string(dev_name, devlink_dev_name(devlink))
-		__string(driver_name, devlink_to_dev(devlink)->driver->name)
+		__string(driver_name, devlink_dev_driver_name(devlink))
 		__string(reporter_name, reporter_name)
 		__string(msg, msg)
 	),
@@ -118,7 +118,7 @@ TRACE_EVENT(devlink_health_recover_aborted,
 	TP_STRUCT__entry(
 		__string(bus_name, devlink_bus_name(devlink))
 		__string(dev_name, devlink_dev_name(devlink))
-		__string(driver_name, devlink_to_dev(devlink)->driver->name)
+		__string(driver_name, devlink_dev_driver_name(devlink))
 		__string(reporter_name, reporter_name)
 		__field(bool, health_state)
 		__field(u64, time_since_last_recover)
@@ -152,7 +152,7 @@ TRACE_EVENT(devlink_health_reporter_state_update,
 	TP_STRUCT__entry(
 		__string(bus_name, devlink_bus_name(devlink))
 		__string(dev_name, devlink_dev_name(devlink))
-		__string(driver_name, devlink_to_dev(devlink)->driver->name)
+		__string(driver_name, devlink_dev_driver_name(devlink))
 		__string(reporter_name, reporter_name)
 		__field(u8, new_state)
 	),
@@ -183,7 +183,7 @@ TRACE_EVENT(devlink_trap_report,
 	TP_STRUCT__entry(
 		__string(bus_name, devlink_bus_name(devlink))
 		__string(dev_name, devlink_dev_name(devlink))
-		__string(driver_name, devlink_to_dev(devlink)->driver->name)
+		__string(driver_name, devlink_dev_driver_name(devlink))
 		__string(trap_name, metadata->trap_name)
 		__string(trap_group_name, metadata->trap_group_name)
 		__array(char, input_dev_name, IFNAMSIZ)
diff --git a/net/devlink/core.c b/net/devlink/core.c
index fcb73d3e56aa..34eb06d88544 100644
--- a/net/devlink/core.c
+++ b/net/devlink/core.c
@@ -260,6 +260,12 @@ const char *devlink_dev_name(const struct devlink *devlink)
 }
 EXPORT_SYMBOL_GPL(devlink_dev_name);
 
+const char *devlink_dev_driver_name(const struct devlink *devlink)
+{
+	return devlink->dev_driver->name;
+}
+EXPORT_SYMBOL_GPL(devlink_dev_driver_name);
+
 struct net *devlink_net(const struct devlink *devlink)
 {
 	return read_pnet(&devlink->_net);
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 09/13] devlink: add devl_warn() helper and use it in port warnings
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (7 preceding siblings ...)
  2026-03-12 10:04 ` [PATCH net-next v4 08/13] devlink: add devlink_dev_driver_name() helper and use it in trace events Jiri Pirko
@ 2026-03-12 10:04 ` Jiri Pirko
  2026-03-12 10:04 ` [PATCH net-next v4 10/13] devlink: allow devlink instance allocation without a backing device Jiri Pirko
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Introduce devl_warn() macro that uses dev_warn() when a backing
device is available and falls back to pr_warn() otherwise. Convert
all dev_warn() calls in port.c to use it, preparing for devlink
instances without a backing device.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v2->v3:
- new patch
---
 net/devlink/devl_internal.h |  9 +++++++++
 net/devlink/port.c          | 14 +++++++-------
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index 3cc7e696e0fd..cb2ffef1ac2d 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -71,6 +71,15 @@ struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size,
 				struct net *net, struct device *dev,
 				const struct device_driver *dev_driver);
 
+#define devl_warn(devlink, format, args...)				\
+	do {								\
+		if ((devlink)->dev)					\
+			dev_warn((devlink)->dev, format, ##args);	\
+		else							\
+			pr_warn("devlink (%s): " format,		\
+				devlink_dev_name(devlink), ##args);	\
+	} while (0)
+
 /* devlink instances are open to the access from the user space after
  * devlink_register() call. Such logical barrier allows us to have certain
  * expectations related to locking.
diff --git a/net/devlink/port.c b/net/devlink/port.c
index fa3e1597711b..7fcd1d3ed44c 100644
--- a/net/devlink/port.c
+++ b/net/devlink/port.c
@@ -976,7 +976,7 @@ static void devlink_port_type_warn(struct work_struct *work)
 	struct devlink_port *port = container_of(to_delayed_work(work),
 						 struct devlink_port,
 						 type_warn_dw);
-	dev_warn(port->devlink->dev, "Type was not set for devlink port.");
+	devl_warn(port->devlink, "Type was not set for devlink port.");
 }
 
 static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
@@ -1242,9 +1242,9 @@ static void __devlink_port_type_set(struct devlink_port *devlink_port,
  */
 void devlink_port_type_eth_set(struct devlink_port *devlink_port)
 {
-	dev_warn(devlink_port->devlink->dev,
-		 "devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
-		 devlink_port->index);
+	devl_warn(devlink_port->devlink,
+		  "devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
+		  devlink_port->index);
 	__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, NULL);
 }
 EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
@@ -1273,9 +1273,9 @@ EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
 void devlink_port_type_clear(struct devlink_port *devlink_port)
 {
 	if (devlink_port->type == DEVLINK_PORT_TYPE_ETH)
-		dev_warn(devlink_port->devlink->dev,
-			 "devlink port type for port %d cleared without a software interface reference, device type not supported by the kernel?\n",
-			 devlink_port->index);
+		devl_warn(devlink_port->devlink,
+			  "devlink port type for port %d cleared without a software interface reference, device type not supported by the kernel?\n",
+			  devlink_port->index);
 	__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
 }
 EXPORT_SYMBOL_GPL(devlink_port_type_clear);
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 10/13] devlink: allow devlink instance allocation without a backing device
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (8 preceding siblings ...)
  2026-03-12 10:04 ` [PATCH net-next v4 09/13] devlink: add devl_warn() helper and use it in port warnings Jiri Pirko
@ 2026-03-12 10:04 ` Jiri Pirko
  2026-03-12 10:04 ` [PATCH net-next v4 11/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Allow devlink_alloc_ns() to be called with dev=NULL to support
device-less devlink instances. When dev is NULL, the instance is
identified over netlink using "devlink_index" as bus_name and
the decimal index value as dev_name.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v2->v3:
- rebased on top of __devlink_alloc() introduction
- removed dev check before dev_warn (devl_warn is used now)
- rebased on top of devlink->bus_name and devlink->dev_name removal
- rebased on top of devlink->dev_driver addition
v1->v2:
- moved DEVLINK_INDEX_BUS_NAME definition to patch #5
- added comment to dev arg that it can be NULL
- fixed the index sprintf for dev-less
---
 net/devlink/core.c          | 23 ++++++++++++++++++-----
 net/devlink/dev.c           |  8 ++++----
 net/devlink/devl_internal.h |  5 +++--
 3 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/net/devlink/core.c b/net/devlink/core.c
index 34eb06d88544..eeb6a71f5f56 100644
--- a/net/devlink/core.c
+++ b/net/devlink/core.c
@@ -250,13 +250,13 @@ EXPORT_SYMBOL_GPL(devlink_to_dev);
 
 const char *devlink_bus_name(const struct devlink *devlink)
 {
-	return devlink->dev->bus->name;
+	return devlink->dev ? devlink->dev->bus->name : DEVLINK_INDEX_BUS_NAME;
 }
 EXPORT_SYMBOL_GPL(devlink_bus_name);
 
 const char *devlink_dev_name(const struct devlink *devlink)
 {
-	return dev_name(devlink->dev);
+	return devlink->dev ? dev_name(devlink->dev) : devlink->dev_name_index;
 }
 EXPORT_SYMBOL_GPL(devlink_dev_name);
 
@@ -329,7 +329,10 @@ static void devlink_release(struct work_struct *work)
 
 	mutex_destroy(&devlink->lock);
 	lockdep_unregister_key(&devlink->lock_key);
-	put_device(devlink->dev);
+	if (devlink->dev)
+		put_device(devlink->dev);
+	else
+		kfree(devlink->dev_name_index);
 	kvfree(devlink);
 }
 
@@ -432,7 +435,7 @@ struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size,
 	static u32 last_id;
 	int ret;
 
-	WARN_ON(!ops || !dev || !dev_driver);
+	WARN_ON(!ops || !dev_driver);
 	if (!devlink_reload_actions_valid(ops))
 		return NULL;
 
@@ -445,7 +448,14 @@ struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size,
 	if (ret < 0)
 		goto err_xa_alloc;
 
-	devlink->dev = get_device(dev);
+	if (dev) {
+		devlink->dev = get_device(dev);
+	} else {
+		devlink->dev_name_index = kasprintf(GFP_KERNEL, "%u", devlink->index);
+		if (!devlink->dev_name_index)
+			goto err_kasprintf;
+	}
+
 	devlink->ops = ops;
 	devlink->dev_driver = dev_driver;
 	xa_init_flags(&devlink->ports, XA_FLAGS_ALLOC);
@@ -471,6 +481,8 @@ struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size,
 
 	return devlink;
 
+err_kasprintf:
+	xa_erase(&devlinks, devlink->index);
 err_xa_alloc:
 	kvfree(devlink);
 	return NULL;
@@ -492,6 +504,7 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
 				 size_t priv_size, struct net *net,
 				 struct device *dev)
 {
+	WARN_ON(!dev);
 	return __devlink_alloc(ops, priv_size, net, dev, dev->driver);
 }
 EXPORT_SYMBOL_GPL(devlink_alloc_ns);
diff --git a/net/devlink/dev.c b/net/devlink/dev.c
index e3a36de4f4ae..57b2b8f03543 100644
--- a/net/devlink/dev.c
+++ b/net/devlink/dev.c
@@ -453,7 +453,8 @@ int devlink_reload(struct devlink *devlink, struct net *dest_net,
 	 * (e.g., PCI reset) and to close possible races between these
 	 * operations and probe/remove.
 	 */
-	device_lock_assert(devlink->dev);
+	if (devlink->dev)
+		device_lock_assert(devlink->dev);
 
 	memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
 	       sizeof(remote_reload_stats));
@@ -854,7 +855,7 @@ int devlink_info_version_running_put_ext(struct devlink_info_req *req,
 }
 EXPORT_SYMBOL_GPL(devlink_info_version_running_put_ext);
 
-static int devlink_nl_driver_info_get(struct device_driver *drv,
+static int devlink_nl_driver_info_get(const struct device_driver *drv,
 				      struct devlink_info_req *req)
 {
 	if (!drv)
@@ -872,7 +873,6 @@ devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
 		     enum devlink_command cmd, u32 portid,
 		     u32 seq, int flags, struct netlink_ext_ack *extack)
 {
-	struct device *dev = devlink_to_dev(devlink);
 	struct devlink_info_req req = {};
 	void *hdr;
 	int err;
@@ -892,7 +892,7 @@ devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
 			goto err_cancel_msg;
 	}
 
-	err = devlink_nl_driver_info_get(dev->driver, &req);
+	err = devlink_nl_driver_info_get(devlink->dev_driver, &req);
 	if (err)
 		goto err_cancel_msg;
 
diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index cb2ffef1ac2d..7dfb7cdd2d23 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -49,6 +49,7 @@ struct devlink {
 	struct xarray snapshot_ids;
 	struct devlink_dev_stats stats;
 	struct device *dev;
+	const char *dev_name_index;
 	const struct device_driver *dev_driver;
 	possible_net_t _net;
 	/* Serializes access to devlink instance specific objects such as
@@ -119,7 +120,7 @@ static inline bool devl_is_registered(struct devlink *devlink)
 
 static inline void devl_dev_lock(struct devlink *devlink, bool dev_lock)
 {
-	if (dev_lock)
+	if (dev_lock && devlink->dev)
 		device_lock(devlink->dev);
 	devl_lock(devlink);
 }
@@ -127,7 +128,7 @@ static inline void devl_dev_lock(struct devlink *devlink, bool dev_lock)
 static inline void devl_dev_unlock(struct devlink *devlink, bool dev_lock)
 {
 	devl_unlock(devlink);
-	if (dev_lock)
+	if (dev_lock && devlink->dev)
 		device_unlock(devlink->dev);
 }
 
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 11/13] devlink: introduce shared devlink instance for PFs on same chip
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (9 preceding siblings ...)
  2026-03-12 10:04 ` [PATCH net-next v4 10/13] devlink: allow devlink instance allocation without a backing device Jiri Pirko
@ 2026-03-12 10:04 ` Jiri Pirko
  2026-03-12 10:04 ` [PATCH net-next v4 12/13] documentation: networking: add shared devlink documentation Jiri Pirko
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Multiple PFs may reside on the same physical chip, running a single
firmware. Some of the resources and configurations may be shared among
these PFs. Currently, there is no good object to pin the configuration
knobs on.

Introduce a shared devlink instance, instantiated upon probe of
the first PF and removed during remove of the last PF. The shared
devlink instance is not backed by any device device, as there is
no PCI device related to it.

The implementation uses reference counting to manage the lifecycle:
each PF that probes calls devlink_shd_get() to get or create
the shared instance, and calls devlink_shd_put() when it removes.
The shared instance is automatically destroyed when the last PF removes.

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>
---
v2->v3:
- added __counter_by() for priv
- added *driver arg to devlink_shd_get()
- added ops, priv_size and driver pointer consistency check
v1->v2:
- s/err_kstrdup_id/err_devlink_free/
- fixed kernel-doc comment of devlink_shd_get()
- removed NULL arg check in devlink_shd_get/put()
---
 include/net/devlink.h |   7 ++
 net/devlink/Makefile  |   2 +-
 net/devlink/sh_dev.c  | 161 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 169 insertions(+), 1 deletion(-)
 create mode 100644 net/devlink/sh_dev.c

diff --git a/include/net/devlink.h b/include/net/devlink.h
index 45dec7067a8e..3038af6ec017 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -1647,6 +1647,13 @@ void devlink_register(struct devlink *devlink);
 void devlink_unregister(struct devlink *devlink);
 void devlink_free(struct devlink *devlink);
 
+struct devlink *devlink_shd_get(const char *id,
+				const struct devlink_ops *ops,
+				size_t priv_size,
+				const struct device_driver *driver);
+void devlink_shd_put(struct devlink *devlink);
+void *devlink_shd_get_priv(struct devlink *devlink);
+
 /**
  * struct devlink_port_ops - Port operations
  * @port_split: Callback used to split the port into multiple ones.
diff --git a/net/devlink/Makefile b/net/devlink/Makefile
index 000da622116a..8f2adb5e5836 100644
--- a/net/devlink/Makefile
+++ b/net/devlink/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-y := core.o netlink.o netlink_gen.o dev.o port.o sb.o dpipe.o \
-	 resource.o param.o region.o health.o trap.o rate.o linecard.o
+	 resource.o param.o region.o health.o trap.o rate.o linecard.o sh_dev.o
diff --git a/net/devlink/sh_dev.c b/net/devlink/sh_dev.c
new file mode 100644
index 000000000000..85acce97e788
--- /dev/null
+++ b/net/devlink/sh_dev.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include <net/devlink.h>
+
+#include "devl_internal.h"
+
+static LIST_HEAD(shd_list);
+static DEFINE_MUTEX(shd_mutex); /* Protects shd_list and shd->list */
+
+/* This structure represents a shared devlink instance,
+ * there is one created per identifier (e.g., serial number).
+ */
+struct devlink_shd {
+	struct list_head list; /* Node in shd list */
+	const char *id; /* Identifier string (e.g., serial number) */
+	refcount_t refcount; /* Reference count */
+	size_t priv_size; /* Size of driver private data */
+	char priv[] __aligned(NETDEV_ALIGN) __counted_by(priv_size);
+};
+
+static struct devlink_shd *devlink_shd_lookup(const char *id)
+{
+	struct devlink_shd *shd;
+
+	list_for_each_entry(shd, &shd_list, list) {
+		if (!strcmp(shd->id, id))
+			return shd;
+	}
+
+	return NULL;
+}
+
+static struct devlink_shd *devlink_shd_create(const char *id,
+					      const struct devlink_ops *ops,
+					      size_t priv_size,
+					      const struct device_driver *driver)
+{
+	struct devlink_shd *shd;
+	struct devlink *devlink;
+
+	devlink = __devlink_alloc(ops, sizeof(struct devlink_shd) + priv_size,
+				  &init_net, NULL, driver);
+	if (!devlink)
+		return NULL;
+	shd = devlink_priv(devlink);
+
+	shd->id = kstrdup(id, GFP_KERNEL);
+	if (!shd->id)
+		goto err_devlink_free;
+	shd->priv_size = priv_size;
+	refcount_set(&shd->refcount, 1);
+
+	devl_lock(devlink);
+	devl_register(devlink);
+	devl_unlock(devlink);
+
+	list_add_tail(&shd->list, &shd_list);
+
+	return shd;
+
+err_devlink_free:
+	devlink_free(devlink);
+	return NULL;
+}
+
+static void devlink_shd_destroy(struct devlink_shd *shd)
+{
+	struct devlink *devlink = priv_to_devlink(shd);
+
+	list_del(&shd->list);
+	devl_lock(devlink);
+	devl_unregister(devlink);
+	devl_unlock(devlink);
+	kfree(shd->id);
+	devlink_free(devlink);
+}
+
+/**
+ * devlink_shd_get - Get or create a shared devlink instance
+ * @id: Identifier string (e.g., serial number) for the shared instance
+ * @ops: Devlink operations structure
+ * @priv_size: Size of private data structure
+ * @driver: Driver associated with the shared devlink instance
+ *
+ * Get an existing shared devlink instance identified by @id, or create
+ * a new one if it doesn't exist. Return the devlink instance with a
+ * reference held. The caller must call devlink_shd_put() when done.
+ *
+ * All callers sharing the same @id must pass identical @ops, @priv_size
+ * and @driver. A mismatch triggers a warning and returns NULL.
+ *
+ * Return: Pointer to the shared devlink instance on success,
+ *         NULL on failure
+ */
+struct devlink *devlink_shd_get(const char *id,
+				const struct devlink_ops *ops,
+				size_t priv_size,
+				const struct device_driver *driver)
+{
+	struct devlink *devlink;
+	struct devlink_shd *shd;
+
+	mutex_lock(&shd_mutex);
+
+	shd = devlink_shd_lookup(id);
+	if (!shd) {
+		shd = devlink_shd_create(id, ops, priv_size, driver);
+		goto unlock;
+	}
+
+	devlink = priv_to_devlink(shd);
+	if (WARN_ON_ONCE(devlink->ops != ops ||
+			 shd->priv_size != priv_size ||
+			 devlink->dev_driver != driver)) {
+		shd = NULL;
+		goto unlock;
+	}
+	refcount_inc(&shd->refcount);
+
+unlock:
+	mutex_unlock(&shd_mutex);
+	return shd ? priv_to_devlink(shd) : NULL;
+}
+EXPORT_SYMBOL_GPL(devlink_shd_get);
+
+/**
+ * devlink_shd_put - Release a reference on a shared devlink instance
+ * @devlink: Shared devlink instance
+ *
+ * Release a reference on a shared devlink instance obtained via
+ * devlink_shd_get().
+ */
+void devlink_shd_put(struct devlink *devlink)
+{
+	struct devlink_shd *shd;
+
+	mutex_lock(&shd_mutex);
+	shd = devlink_priv(devlink);
+	if (refcount_dec_and_test(&shd->refcount))
+		devlink_shd_destroy(shd);
+	mutex_unlock(&shd_mutex);
+}
+EXPORT_SYMBOL_GPL(devlink_shd_put);
+
+/**
+ * devlink_shd_get_priv - Get private data from shared devlink instance
+ * @devlink: Devlink instance
+ *
+ * Returns a pointer to the driver's private data structure within
+ * the shared devlink instance.
+ *
+ * Return: Pointer to private data
+ */
+void *devlink_shd_get_priv(struct devlink *devlink)
+{
+	struct devlink_shd *shd = devlink_priv(devlink);
+
+	return shd->priv;
+}
+EXPORT_SYMBOL_GPL(devlink_shd_get_priv);
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 12/13] documentation: networking: add shared devlink documentation
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (10 preceding siblings ...)
  2026-03-12 10:04 ` [PATCH net-next v4 11/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
@ 2026-03-12 10:04 ` Jiri Pirko
  2026-03-12 10:04 ` [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip Jiri Pirko
  2026-03-14 20:20 ` [PATCH net-next v4 00/13] devlink: introduce " patchwork-bot+netdevbpf
  13 siblings, 0 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

Document shared devlink instances for multiple PFs on the same chip.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v2->v3:
- describing 2 models of use os shared device, with and without per-PF
  instances
v1->v2:
- fixed number of "="'s
---
 .../networking/devlink/devlink-shared.rst     | 97 +++++++++++++++++++
 Documentation/networking/devlink/index.rst    |  1 +
 2 files changed, 98 insertions(+)
 create mode 100644 Documentation/networking/devlink/devlink-shared.rst

diff --git a/Documentation/networking/devlink/devlink-shared.rst b/Documentation/networking/devlink/devlink-shared.rst
new file mode 100644
index 000000000000..16bf6a7d25d9
--- /dev/null
+++ b/Documentation/networking/devlink/devlink-shared.rst
@@ -0,0 +1,97 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========================
+Devlink Shared Instances
+========================
+
+Overview
+========
+
+Shared devlink instances allow multiple physical functions (PFs) on the same
+chip to share a devlink instance for chip-wide operations.
+
+Multiple PFs may reside on the same physical chip, running a single firmware.
+Some of the resources and configurations may be shared among these PFs. The
+shared devlink instance provides an object to pin configuration knobs on.
+
+There are two possible usage models:
+
+1. The shared devlink instance is used alongside individual PF devlink
+   instances, providing chip-wide configuration in addition to per-PF
+   configuration.
+2. The shared devlink instance is the only devlink instance, without
+   per-PF instances.
+
+It is up to the driver to decide which usage model to use.
+
+The shared devlink instance is not backed by any struct *device*.
+
+Implementation
+==============
+
+Architecture
+------------
+
+The implementation uses:
+
+* **Chip identification**: PFs are grouped by chip using a driver-specific identifier
+* **Shared instance management**: Global list of shared instances with reference counting
+
+API Functions
+-------------
+
+The following functions are provided for managing shared devlink instances:
+
+* ``devlink_shd_get()``: Get or create a shared devlink instance identified by a string ID
+* ``devlink_shd_put()``: Release a reference on a shared devlink instance
+* ``devlink_shd_get_priv()``: Get private data from shared devlink instance
+
+Initialization Flow
+-------------------
+
+1. **PF calls shared devlink init** during driver probe
+2. **Chip identification** using driver-specific method to determine device identity
+3. **Get or create shared instance** using ``devlink_shd_get()``:
+
+   * The function looks up existing instance by identifier
+   * If none exists, creates new instance:
+     - Allocates and registers devlink instance
+     - Adds to global shared instances list
+     - Increments reference count
+
+4. **Set nested devlink instance** for the PF devlink instance using
+   ``devl_nested_devlink_set()`` before registering the PF devlink instance
+
+Cleanup Flow
+------------
+
+1. **Cleanup** when PF is removed
+2. **Call** ``devlink_shd_put()`` to release reference (decrements reference count)
+3. **Shared instance is automatically destroyed** when the last PF removes (reference count reaches zero)
+
+Chip Identification
+-------------------
+
+PFs belonging to the same chip are identified using a driver-specific method.
+The driver is free to choose any identifier that is suitable for determining
+whether two PFs are part of the same device. Examples include:
+
+* **PCI VPD serial numbers**: Extract from PCI VPD
+* **Device tree properties**: Read chip identifier from device tree
+* **Other hardware-specific identifiers**: Any unique identifier that groups PFs by chip
+
+Locking
+-------
+
+A global mutex (``shd_mutex``) protects the shared instances list during registration/deregistration.
+
+Similarly to other nested devlink instance relationships, devlink lock of
+the shared instance should be always taken after the devlink lock of PF.
+
+Reference Counting
+------------------
+
+Each shared devlink instance maintains a reference count (``refcount_t refcount``).
+The reference count is incremented when ``devlink_shd_get()`` is called and decremented
+when ``devlink_shd_put()`` is called. When the reference count reaches zero, the shared
+instance is automatically destroyed.
diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst
index 35b12a2bfeba..f7ba7dcf477d 100644
--- a/Documentation/networking/devlink/index.rst
+++ b/Documentation/networking/devlink/index.rst
@@ -68,6 +68,7 @@ general.
    devlink-resource
    devlink-selftests
    devlink-trap
+   devlink-shared
 
 Driver-specific documentation
 -----------------------------
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (11 preceding siblings ...)
  2026-03-12 10:04 ` [PATCH net-next v4 12/13] documentation: networking: add shared devlink documentation Jiri Pirko
@ 2026-03-12 10:04 ` Jiri Pirko
  2026-03-20 23:16   ` Adam Young
  2026-03-24 15:10   ` [PATCH net-next v4 13/15] " Ben Copeland
  2026-03-14 20:20 ` [PATCH net-next v4 00/13] devlink: introduce " patchwork-bot+netdevbpf
  13 siblings, 2 replies; 24+ messages in thread
From: Jiri Pirko @ 2026-03-12 10:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

From: Jiri Pirko <jiri@nvidia.com>

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>
---
v2->v3:
- removed "const" from "sn"
- passing driver pointer to devlink_shd_get()
---
 .../net/ethernet/mellanox/mlx5/core/Makefile  |  5 +-
 .../net/ethernet/mellanox/mlx5/core/main.c    | 17 ++++++
 .../ethernet/mellanox/mlx5/core/sh_devlink.c  | 61 +++++++++++++++++++
 .../ethernet/mellanox/mlx5/core/sh_devlink.h  | 12 ++++
 include/linux/mlx5/driver.h                   |  1 +
 5 files changed, 94 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
 create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index 8ffa286a18f5..d39fe9c4a87c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -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
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index fdc3ba20912e..1c35c3fc3bb3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -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
index 000000000000..bc33f95302df
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
@@ -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
index 000000000000..8ab8d6940227
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
@@ -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__ */
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 04dcd09f7517..1268fcf35ec7 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -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 {
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip
  2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
                   ` (12 preceding siblings ...)
  2026-03-12 10:04 ` [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip Jiri Pirko
@ 2026-03-14 20:20 ` patchwork-bot+netdevbpf
  13 siblings, 0 replies; 24+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-03-14 20:20 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, edumazet, kuba, pabeni, horms, donald.hunter,
	corbet, skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel,
	mschmidt, andrew+netdev, rostedt, mhiramat, mathieu.desnoyers,
	chuck.lever, matttbe, cjubran, daniel.zahka, linux-doc,
	linux-rdma, linux-trace-kernel

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Thu, 12 Mar 2026 11:03:54 +0100 you wrote:
> From: Jiri Pirko <jiri@nvidia.com>
> 
> Multiple PFs on a network adapter often reside on the same physical
> chip, running a single firmware. Some resources and configurations
> are inherently shared among these PFs - PTP clocks, VF group rates,
> firmware parameters, and others. Today there is no good object in
> the devlink model to attach these chip-wide configuration knobs to.
> Drivers resort to workarounds like pinning shared state to PF0 or
> maintaining ad-hoc internal structures (e.g., ice_adapter) that are
> invisible to userspace.
> 
> [...]

Here is the summary with links:
  - [net-next,v4,01/13] devlink: expose devlink instance index over netlink
    https://git.kernel.org/netdev/net-next/c/68deca0f0f4b
  - [net-next,v4,02/13] devlink: add helpers to get bus_name/dev_name
    https://git.kernel.org/netdev/net-next/c/0f5531879afb
  - [net-next,v4,03/13] devlink: avoid extra iterations when found devlink is not registered
    https://git.kernel.org/netdev/net-next/c/e2e3666fd360
  - [net-next,v4,04/13] devlink: allow to use devlink index as a command handle
    https://git.kernel.org/netdev/net-next/c/d85a8af57da8
  - [net-next,v4,05/13] devlink: support index-based lookup via bus_name/dev_name handle
    https://git.kernel.org/netdev/net-next/c/725d5fdb7b9c
  - [net-next,v4,06/13] devlink: support index-based notification filtering
    https://git.kernel.org/netdev/net-next/c/089aeb4f2218
  - [net-next,v4,07/13] devlink: introduce __devlink_alloc() with dev driver pointer
    https://git.kernel.org/netdev/net-next/c/eb32a6310a7b
  - [net-next,v4,08/13] devlink: add devlink_dev_driver_name() helper and use it in trace events
    https://git.kernel.org/netdev/net-next/c/20b0f383aae7
  - [net-next,v4,09/13] devlink: add devl_warn() helper and use it in port warnings
    https://git.kernel.org/netdev/net-next/c/104733e1303e
  - [net-next,v4,10/13] devlink: allow devlink instance allocation without a backing device
    https://git.kernel.org/netdev/net-next/c/a4c6d53e5fd6
  - [net-next,v4,11/13] devlink: introduce shared devlink instance for PFs on same chip
    https://git.kernel.org/netdev/net-next/c/1850e76b3804
  - [net-next,v4,12/13] documentation: networking: add shared devlink documentation
    https://git.kernel.org/netdev/net-next/c/63fff8c0f702
  - [net-next,v4,13/13] net/mlx5: Add a shared devlink instance for PFs on same chip
    https://git.kernel.org/netdev/net-next/c/2a8c8a03f306

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-12 10:04 ` [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip Jiri Pirko
@ 2026-03-20 23:16   ` Adam Young
  2026-03-20 23:37     ` Adam Young
  2026-03-24 15:10   ` [PATCH net-next v4 13/15] " Ben Copeland
  1 sibling, 1 reply; 24+ messages in thread
From: Adam Young @ 2026-03-20 23:16 UTC (permalink / raw)
  To: Jiri Pirko, netdev
  Cc: davem, edumazet, kuba, pabeni, horms, donald.hunter, corbet,
	skhan, saeedm, leon, tariqt, mbloch, przemyslaw.kitszel, mschmidt,
	andrew+netdev, rostedt, mhiramat, mathieu.desnoyers, chuck.lever,
	matttbe, cjubran, daniel.zahka, linux-doc, linux-rdma,
	linux-trace-kernel

This breaks on my system:

On 7.0.0 It boots fine.  With net-next/main currently at this commit


commit 8737d7194d6d5947c3d7d8813895b44a25b84477 (net-next/main, 
net-next/HEAD)
Author: Lorenzo Bianconi <lorenzo@kernel.org>
Date:   Fri Mar 13 17:28:36 2026 +0100

I get:

[   21.859081] mlx5_core 0005:01:00.0: probe_one:2017:(pid 10): 
mlx5_shd_init failed with error code -2
[   21.863266] mlx5_core 0005:01:00.0: probe with driver mlx5_core 
failed with error -2
[   21.866360] mlx5_core 0005:01:00.1: probe_one:2017:(pid 10): 
mlx5_shd_init failed with error code -2
[   21.869937] mlx5_core 0005:01:00.1: probe with driver mlx5_core 
failed with error -2


I am happy to help debug:   what do you need from me?


On 3/12/26 06:04, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@nvidia.com>
>
> 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>
> ---
> v2->v3:
> - removed "const" from "sn"
> - passing driver pointer to devlink_shd_get()
> ---
>   .../net/ethernet/mellanox/mlx5/core/Makefile  |  5 +-
>   .../net/ethernet/mellanox/mlx5/core/main.c    | 17 ++++++
>   .../ethernet/mellanox/mlx5/core/sh_devlink.c  | 61 +++++++++++++++++++
>   .../ethernet/mellanox/mlx5/core/sh_devlink.h  | 12 ++++
>   include/linux/mlx5/driver.h                   |  1 +
>   5 files changed, 94 insertions(+), 2 deletions(-)
>   create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>   create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> index 8ffa286a18f5..d39fe9c4a87c 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> @@ -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
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
> index fdc3ba20912e..1c35c3fc3bb3 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
> @@ -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
> index 000000000000..bc33f95302df
> --- /dev/null
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
> @@ -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
> index 000000000000..8ab8d6940227
> --- /dev/null
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
> @@ -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__ */
> diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
> index 04dcd09f7517..1268fcf35ec7 100644
> --- a/include/linux/mlx5/driver.h
> +++ b/include/linux/mlx5/driver.h
> @@ -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 {

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-20 23:16   ` Adam Young
@ 2026-03-20 23:37     ` Adam Young
  2026-03-23 15:05       ` Jiri Pirko
  0 siblings, 1 reply; 24+ messages in thread
From: Adam Young @ 2026-03-20 23:37 UTC (permalink / raw)
  To: Jiri Pirko, netdev



0005:01:00.0 Ethernet controller: Mellanox Technologies MT27710 Family 
[ConnectX-4 Lx]
0005:01:00.1 Ethernet controller: Mellanox Technologies MT27710 Family 
[ConnectX-4 Lx]

On 3/20/26 19:16, Adam Young wrote:
> This breaks on my system:
>
> On 7.0.0 It boots fine.  With net-next/main currently at this commit
>
>
> commit 8737d7194d6d5947c3d7d8813895b44a25b84477 (net-next/main, 
> net-next/HEAD)
> Author: Lorenzo Bianconi <lorenzo@kernel.org>
> Date:   Fri Mar 13 17:28:36 2026 +0100
>
> I get:
>
> [   21.859081] mlx5_core 0005:01:00.0: probe_one:2017:(pid 10): 
> mlx5_shd_init failed with error code -2
> [   21.863266] mlx5_core 0005:01:00.0: probe with driver mlx5_core 
> failed with error -2
> [   21.866360] mlx5_core 0005:01:00.1: probe_one:2017:(pid 10): 
> mlx5_shd_init failed with error code -2
> [   21.869937] mlx5_core 0005:01:00.1: probe with driver mlx5_core 
> failed with error -2
>
>
> I am happy to help debug:   what do you need from me?
>
>
> On 3/12/26 06:04, Jiri Pirko wrote:
>> From: Jiri Pirko <jiri@nvidia.com>
>>
>> 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>
>> ---
>> v2->v3:
>> - removed "const" from "sn"
>> - passing driver pointer to devlink_shd_get()
>> ---
>>   .../net/ethernet/mellanox/mlx5/core/Makefile  |  5 +-
>>   .../net/ethernet/mellanox/mlx5/core/main.c    | 17 ++++++
>>   .../ethernet/mellanox/mlx5/core/sh_devlink.c  | 61 +++++++++++++++++++
>>   .../ethernet/mellanox/mlx5/core/sh_devlink.h  | 12 ++++
>>   include/linux/mlx5/driver.h                   |  1 +
>>   5 files changed, 94 insertions(+), 2 deletions(-)
>>   create mode 100644 
>> drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>>   create mode 100644 
>> drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>>
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile 
>> b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> index 8ffa286a18f5..d39fe9c4a87c 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> @@ -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
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c 
>> b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>> index fdc3ba20912e..1c35c3fc3bb3 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>> @@ -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
>> index 000000000000..bc33f95302df
>> --- /dev/null
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>> @@ -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
>> index 000000000000..8ab8d6940227
>> --- /dev/null
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>> @@ -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__ */
>> diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
>> index 04dcd09f7517..1268fcf35ec7 100644
>> --- a/include/linux/mlx5/driver.h
>> +++ b/include/linux/mlx5/driver.h
>> @@ -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 {
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-20 23:37     ` Adam Young
@ 2026-03-23 15:05       ` Jiri Pirko
  2026-03-24 13:02         ` Jiri Pirko
  0 siblings, 1 reply; 24+ messages in thread
From: Jiri Pirko @ 2026-03-23 15:05 UTC (permalink / raw)
  To: Adam Young; +Cc: netdev

Sat, Mar 21, 2026 at 12:37:06AM +0100, admiyo@amperemail.onmicrosoft.com wrote:
>
>
>0005:01:00.0 Ethernet controller: Mellanox Technologies MT27710 Family
>[ConnectX-4 Lx]

Cool. Will try to reproduce this locally. Thanks!




>0005:01:00.1 Ethernet controller: Mellanox Technologies MT27710 Family
>[ConnectX-4 Lx]
>
>On 3/20/26 19:16, Adam Young wrote:
>> This breaks on my system:
>> 
>> On 7.0.0 It boots fine.  With net-next/main currently at this commit
>> 
>> 
>> commit 8737d7194d6d5947c3d7d8813895b44a25b84477 (net-next/main,
>> net-next/HEAD)
>> Author: Lorenzo Bianconi <lorenzo@kernel.org>
>> Date:   Fri Mar 13 17:28:36 2026 +0100
>> 
>> I get:
>> 
>> [   21.859081] mlx5_core 0005:01:00.0: probe_one:2017:(pid 10):
>> mlx5_shd_init failed with error code -2
>> [   21.863266] mlx5_core 0005:01:00.0: probe with driver mlx5_core failed
>> with error -2
>> [   21.866360] mlx5_core 0005:01:00.1: probe_one:2017:(pid 10):
>> mlx5_shd_init failed with error code -2
>> [   21.869937] mlx5_core 0005:01:00.1: probe with driver mlx5_core failed
>> with error -2
>> 
>> 
>> I am happy to help debug:   what do you need from me?
>> 
>> 
>> On 3/12/26 06:04, Jiri Pirko wrote:
>> > From: Jiri Pirko <jiri@nvidia.com>
>> > 
>> > 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>
>> > ---
>> > v2->v3:
>> > - removed "const" from "sn"
>> > - passing driver pointer to devlink_shd_get()
>> > ---
>> >   .../net/ethernet/mellanox/mlx5/core/Makefile  |  5 +-
>> >   .../net/ethernet/mellanox/mlx5/core/main.c    | 17 ++++++
>> >   .../ethernet/mellanox/mlx5/core/sh_devlink.c  | 61 +++++++++++++++++++
>> >   .../ethernet/mellanox/mlx5/core/sh_devlink.h  | 12 ++++
>> >   include/linux/mlx5/driver.h                   |  1 +
>> >   5 files changed, 94 insertions(+), 2 deletions(-)
>> >   create mode 100644
>> > drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>> >   create mode 100644
>> > drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>> > 
>> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> > b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> > index 8ffa286a18f5..d39fe9c4a87c 100644
>> > --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>> > @@ -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
>> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>> > b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>> > index fdc3ba20912e..1c35c3fc3bb3 100644
>> > --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>> > @@ -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
>> > index 000000000000..bc33f95302df
>> > --- /dev/null
>> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>> > @@ -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
>> > index 000000000000..8ab8d6940227
>> > --- /dev/null
>> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>> > @@ -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__ */
>> > diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
>> > index 04dcd09f7517..1268fcf35ec7 100644
>> > --- a/include/linux/mlx5/driver.h
>> > +++ b/include/linux/mlx5/driver.h
>> > @@ -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 {
>> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-23 15:05       ` Jiri Pirko
@ 2026-03-24 13:02         ` Jiri Pirko
  2026-03-24 17:49           ` Adam Young
  0 siblings, 1 reply; 24+ messages in thread
From: Jiri Pirko @ 2026-03-24 13:02 UTC (permalink / raw)
  To: Adam Young; +Cc: netdev

Mon, Mar 23, 2026 at 04:05:19PM +0100, jiri@resnulli.us wrote:
>Sat, Mar 21, 2026 at 12:37:06AM +0100, admiyo@amperemail.onmicrosoft.com wrote:
>>
>>
>>0005:01:00.0 Ethernet controller: Mellanox Technologies MT27710 Family
>>[ConnectX-4 Lx]
>
>Cool. Will try to reproduce this locally. Thanks!
>

Hi. Testing this with:
08:00.0 Ethernet controller: Mellanox Technologies MT27710 Family [ConnectX-4 Lx]
works fine. What's your output of "devlink dev info"?


>
>
>
>>0005:01:00.1 Ethernet controller: Mellanox Technologies MT27710 Family
>>[ConnectX-4 Lx]
>>
>>On 3/20/26 19:16, Adam Young wrote:
>>> This breaks on my system:
>>> 
>>> On 7.0.0 It boots fine.  With net-next/main currently at this commit
>>> 
>>> 
>>> commit 8737d7194d6d5947c3d7d8813895b44a25b84477 (net-next/main,
>>> net-next/HEAD)
>>> Author: Lorenzo Bianconi <lorenzo@kernel.org>
>>> Date:   Fri Mar 13 17:28:36 2026 +0100
>>> 
>>> I get:
>>> 
>>> [   21.859081] mlx5_core 0005:01:00.0: probe_one:2017:(pid 10):
>>> mlx5_shd_init failed with error code -2
>>> [   21.863266] mlx5_core 0005:01:00.0: probe with driver mlx5_core failed
>>> with error -2
>>> [   21.866360] mlx5_core 0005:01:00.1: probe_one:2017:(pid 10):
>>> mlx5_shd_init failed with error code -2
>>> [   21.869937] mlx5_core 0005:01:00.1: probe with driver mlx5_core failed
>>> with error -2
>>> 
>>> 
>>> I am happy to help debug:   what do you need from me?
>>> 
>>> 
>>> On 3/12/26 06:04, Jiri Pirko wrote:
>>> > From: Jiri Pirko <jiri@nvidia.com>
>>> > 
>>> > 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>
>>> > ---
>>> > v2->v3:
>>> > - removed "const" from "sn"
>>> > - passing driver pointer to devlink_shd_get()
>>> > ---
>>> >   .../net/ethernet/mellanox/mlx5/core/Makefile  |  5 +-
>>> >   .../net/ethernet/mellanox/mlx5/core/main.c    | 17 ++++++
>>> >   .../ethernet/mellanox/mlx5/core/sh_devlink.c  | 61 +++++++++++++++++++
>>> >   .../ethernet/mellanox/mlx5/core/sh_devlink.h  | 12 ++++
>>> >   include/linux/mlx5/driver.h                   |  1 +
>>> >   5 files changed, 94 insertions(+), 2 deletions(-)
>>> >   create mode 100644
>>> > drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>>> >   create mode 100644
>>> > drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>>> > 
>>> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>> > b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>> > index 8ffa286a18f5..d39fe9c4a87c 100644
>>> > --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>> > @@ -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
>>> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>> > b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>> > index fdc3ba20912e..1c35c3fc3bb3 100644
>>> > --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>> > @@ -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
>>> > index 000000000000..bc33f95302df
>>> > --- /dev/null
>>> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>>> > @@ -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
>>> > index 000000000000..8ab8d6940227
>>> > --- /dev/null
>>> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>>> > @@ -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__ */
>>> > diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
>>> > index 04dcd09f7517..1268fcf35ec7 100644
>>> > --- a/include/linux/mlx5/driver.h
>>> > +++ b/include/linux/mlx5/driver.h
>>> > @@ -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 {
>>> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/15] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-12 10:04 ` [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip Jiri Pirko
  2026-03-20 23:16   ` Adam Young
@ 2026-03-24 15:10   ` Ben Copeland
  2026-03-24 15:21     ` Jiri Pirko
  1 sibling, 1 reply; 24+ messages in thread
From: Ben Copeland @ 2026-03-24 15:10 UTC (permalink / raw)
  To: jiri; +Cc: netdev, kuba, Ben Copeland

Hi Jiri,

This breaks probe on AmpereOne systems where VPD has no serial number:

[    0.839394] mlx5_core 0000:01:00.0: probe_one:1952:(pid 10): mlx5_shd_init failed with error code -2
[    0.846302] mlx5_core 0000:01:00.0: probe with driver mlx5_core failed with error -2

Returning 0 instead of -ENOENT when no SN is found fixes it:

--- a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
@@ -33,7 +33,7 @@ int mlx5_shd_init(struct mlx5_core_dev *dev)
 		start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
 						     PCI_VPD_RO_KEYWORD_SERIALNO, &kw_len);
 		if (start < 0)
-			return -ENOENT;
+			return 0;
 	}

Thanks,
Ben

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/15] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-24 15:10   ` [PATCH net-next v4 13/15] " Ben Copeland
@ 2026-03-24 15:21     ` Jiri Pirko
  2026-03-24 15:37       ` Ben Copeland
  0 siblings, 1 reply; 24+ messages in thread
From: Jiri Pirko @ 2026-03-24 15:21 UTC (permalink / raw)
  To: Ben Copeland; +Cc: jiri, netdev, kuba

Tue, Mar 24, 2026 at 04:10:14PM +0100, ben.copeland@linaro.org wrote:
>Hi Jiri,
>
>This breaks probe on AmpereOne systems where VPD has no serial number:
>
>[    0.839394] mlx5_core 0000:01:00.0: probe_one:1952:(pid 10): mlx5_shd_init failed with error code -2
>[    0.846302] mlx5_core 0000:01:00.0: probe with driver mlx5_core failed with error -2
>
>Returning 0 instead of -ENOENT when no SN is found fixes it:
>
>--- a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>+++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>@@ -33,7 +33,7 @@ int mlx5_shd_init(struct mlx5_core_dev *dev)
> 		start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
> 						     PCI_VPD_RO_KEYWORD_SERIALNO, &kw_len);
> 		if (start < 0)
>-			return -ENOENT;
>+			return 0;

Okay. That is probably the best fall-back. Do you want to send the fix,
or should I?


> 	}
>
>Thanks,
>Ben
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/15] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-24 15:21     ` Jiri Pirko
@ 2026-03-24 15:37       ` Ben Copeland
  0 siblings, 0 replies; 24+ messages in thread
From: Ben Copeland @ 2026-03-24 15:37 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: jiri, netdev, kuba

On Tue, 24 Mar 2026 at 15:21, Jiri Pirko <jiri@resnulli.us> wrote:
>
> Tue, Mar 24, 2026 at 04:10:14PM +0100, ben.copeland@linaro.org wrote:
> >Hi Jiri,
> >
> >This breaks probe on AmpereOne systems where VPD has no serial number:
> >
> >[    0.839394] mlx5_core 0000:01:00.0: probe_one:1952:(pid 10): mlx5_shd_init failed with error code -2
> >[    0.846302] mlx5_core 0000:01:00.0: probe with driver mlx5_core failed with error -2
> >
> >Returning 0 instead of -ENOENT when no SN is found fixes it:
> >
> >--- a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
> >+++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
> >@@ -33,7 +33,7 @@ int mlx5_shd_init(struct mlx5_core_dev *dev)
> >               start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
> >                                                    PCI_VPD_RO_KEYWORD_SERIALNO, &kw_len);
> >               if (start < 0)
> >-                      return -ENOENT;
> >+                      return 0;
>
> Okay. That is probably the best fall-back. Do you want to send the fix,
> or should I?

I will leave it with you.

Thanks,

Ben

>
>
> >       }
> >
> >Thanks,
> >Ben
> >

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-24 13:02         ` Jiri Pirko
@ 2026-03-24 17:49           ` Adam Young
  2026-03-24 19:57             ` Adam Young
  0 siblings, 1 reply; 24+ messages in thread
From: Adam Young @ 2026-03-24 17:49 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev


On 3/24/26 09:02, Jiri Pirko wrote:
> Mon, Mar 23, 2026 at 04:05:19PM +0100, jiri@resnulli.us wrote:
>> Sat, Mar 21, 2026 at 12:37:06AM +0100, admiyo@amperemail.onmicrosoft.com wrote:
>>>
>>> 0005:01:00.0 Ethernet controller: Mellanox Technologies MT27710 Family
>>> [ConnectX-4 Lx]
>> Cool. Will try to reproduce this locally. Thanks!
>>
> Hi. Testing this with:
> 08:00.0 Ethernet controller: Mellanox Technologies MT27710 Family [ConnectX-4 Lx]
> works fine. What's your output of "devlink dev info"?

Running on 6.18.6:

# devlink dev info
pci/0005:01:00.0:
   driver mlx5_core
   versions:
       fixed:
         fw.psid MT_2420110034
       running:
         fw.version 14.32.1010
         fw 14.32.1010
       stored:
         fw.version 14.32.1010
         fw 14.32.1010
auxiliary/mlx5_core.eth.0:
   driver mlx5_core.eth
pci/0005:01:00.1:
   driver mlx5_core
   versions:
       fixed:
         fw.psid MT_2420110034
       running:
         fw.version 14.32.1010
         fw 14.32.1010
       stored:
         fw.version 14.32.1010
         fw 14.32.1010
auxiliary/mlx5_core.eth.1:
   driver mlx5_core.eth



>
>
>>
>>
>>> 0005:01:00.1 Ethernet controller: Mellanox Technologies MT27710 Family
>>> [ConnectX-4 Lx]
>>>
>>> On 3/20/26 19:16, Adam Young wrote:
>>>> This breaks on my system:
>>>>
>>>> On 7.0.0 It boots fine.  With net-next/main currently at this commit
>>>>
>>>>
>>>> commit 8737d7194d6d5947c3d7d8813895b44a25b84477 (net-next/main,
>>>> net-next/HEAD)
>>>> Author: Lorenzo Bianconi <lorenzo@kernel.org>
>>>> Date:   Fri Mar 13 17:28:36 2026 +0100
>>>>
>>>> I get:
>>>>
>>>> [   21.859081] mlx5_core 0005:01:00.0: probe_one:2017:(pid 10):
>>>> mlx5_shd_init failed with error code -2
>>>> [   21.863266] mlx5_core 0005:01:00.0: probe with driver mlx5_core failed
>>>> with error -2
>>>> [   21.866360] mlx5_core 0005:01:00.1: probe_one:2017:(pid 10):
>>>> mlx5_shd_init failed with error code -2
>>>> [   21.869937] mlx5_core 0005:01:00.1: probe with driver mlx5_core failed
>>>> with error -2
>>>>
>>>>
>>>> I am happy to help debug:   what do you need from me?
>>>>
>>>>
>>>> On 3/12/26 06:04, Jiri Pirko wrote:
>>>>> From: Jiri Pirko <jiri@nvidia.com>
>>>>>
>>>>> 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>
>>>>> ---
>>>>> v2->v3:
>>>>> - removed "const" from "sn"
>>>>> - passing driver pointer to devlink_shd_get()
>>>>> ---
>>>>>    .../net/ethernet/mellanox/mlx5/core/Makefile  |  5 +-
>>>>>    .../net/ethernet/mellanox/mlx5/core/main.c    | 17 ++++++
>>>>>    .../ethernet/mellanox/mlx5/core/sh_devlink.c  | 61 +++++++++++++++++++
>>>>>    .../ethernet/mellanox/mlx5/core/sh_devlink.h  | 12 ++++
>>>>>    include/linux/mlx5/driver.h                   |  1 +
>>>>>    5 files changed, 94 insertions(+), 2 deletions(-)
>>>>>    create mode 100644
>>>>> drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>>>>>    create mode 100644
>>>>> drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>>>>>
>>>>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>>>> b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>>>> index 8ffa286a18f5..d39fe9c4a87c 100644
>>>>> --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>>>> @@ -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
>>>>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>>>> b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>>>> index fdc3ba20912e..1c35c3fc3bb3 100644
>>>>> --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>>>> @@ -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
>>>>> index 000000000000..bc33f95302df
>>>>> --- /dev/null
>>>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>>>>> @@ -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
>>>>> index 000000000000..8ab8d6940227
>>>>> --- /dev/null
>>>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>>>>> @@ -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__ */
>>>>> diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
>>>>> index 04dcd09f7517..1268fcf35ec7 100644
>>>>> --- a/include/linux/mlx5/driver.h
>>>>> +++ b/include/linux/mlx5/driver.h
>>>>> @@ -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 {

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip
  2026-03-24 17:49           ` Adam Young
@ 2026-03-24 19:57             ` Adam Young
  0 siblings, 0 replies; 24+ messages in thread
From: Adam Young @ 2026-03-24 19:57 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev


On 3/24/26 13:49, Adam Young wrote:
>
> On 3/24/26 09:02, Jiri Pirko wrote:
>> Mon, Mar 23, 2026 at 04:05:19PM +0100, jiri@resnulli.us wrote:
>>> Sat, Mar 21, 2026 at 12:37:06AM +0100, 
>>> admiyo@amperemail.onmicrosoft.com wrote:
>>>>
>>>> 0005:01:00.0 Ethernet controller: Mellanox Technologies MT27710 Family
>>>> [ConnectX-4 Lx]
>>> Cool. Will try to reproduce this locally. Thanks!
>>>
>> Hi. Testing this with:
>> 08:00.0 Ethernet controller: Mellanox Technologies MT27710 Family 
>> [ConnectX-4 Lx]
>> works fine. What's your output of "devlink dev info"?
>
> Running on 6.18.6:
>
> # devlink dev info
> pci/0005:01:00.0:
>   driver mlx5_core
>   versions:
>       fixed:
>         fw.psid MT_2420110034
>       running:
>         fw.version 14.32.1010
>         fw 14.32.1010
>       stored:
>         fw.version 14.32.1010
>         fw 14.32.1010
> auxiliary/mlx5_core.eth.0:
>   driver mlx5_core.eth
> pci/0005:01:00.1:
>   driver mlx5_core
>   versions:
>       fixed:
>         fw.psid MT_2420110034
>       running:
>         fw.version 14.32.1010
>         fw 14.32.1010
>       stored:
>         fw.version 14.32.1010
>         fw 14.32.1010
> auxiliary/mlx5_core.eth.1:
>   driver mlx5_core.eth
>
I just confirmed that the error is the failure to look up the SN or V3 
keyword.  The following ugly actually brought up the adapter:

@@ -32,12 +34,14 @@ int mlx5_shd_init(struct mlx5_core_dev *dev)
                 /* 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 (start < 0)
+               sn = kstrndup("random", 6, GFP_KERNEL);
+       else
+               sn = kstrndup(vpd_data + start, kw_len, GFP_KERNEL);
         if (!sn)
                 return -ENOMEM;
+

SO I think you need something other than sn to key off of to name the 
shd (if I understand the code correctly)



>
>
>>
>>
>>>
>>>
>>>> 0005:01:00.1 Ethernet controller: Mellanox Technologies MT27710 Family
>>>> [ConnectX-4 Lx]
>>>>
>>>> On 3/20/26 19:16, Adam Young wrote:
>>>>> This breaks on my system:
>>>>>
>>>>> On 7.0.0 It boots fine.  With net-next/main currently at this commit
>>>>>
>>>>>
>>>>> commit 8737d7194d6d5947c3d7d8813895b44a25b84477 (net-next/main,
>>>>> net-next/HEAD)
>>>>> Author: Lorenzo Bianconi <lorenzo@kernel.org>
>>>>> Date:   Fri Mar 13 17:28:36 2026 +0100
>>>>>
>>>>> I get:
>>>>>
>>>>> [   21.859081] mlx5_core 0005:01:00.0: probe_one:2017:(pid 10):
>>>>> mlx5_shd_init failed with error code -2
>>>>> [   21.863266] mlx5_core 0005:01:00.0: probe with driver mlx5_core 
>>>>> failed
>>>>> with error -2
>>>>> [   21.866360] mlx5_core 0005:01:00.1: probe_one:2017:(pid 10):
>>>>> mlx5_shd_init failed with error code -2
>>>>> [   21.869937] mlx5_core 0005:01:00.1: probe with driver mlx5_core 
>>>>> failed
>>>>> with error -2
>>>>>
>>>>>
>>>>> I am happy to help debug:   what do you need from me?
>>>>>
>>>>>
>>>>> On 3/12/26 06:04, Jiri Pirko wrote:
>>>>>> From: Jiri Pirko <jiri@nvidia.com>
>>>>>>
>>>>>> 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>
>>>>>> ---
>>>>>> v2->v3:
>>>>>> - removed "const" from "sn"
>>>>>> - passing driver pointer to devlink_shd_get()
>>>>>> ---
>>>>>>    .../net/ethernet/mellanox/mlx5/core/Makefile  |  5 +-
>>>>>>    .../net/ethernet/mellanox/mlx5/core/main.c    | 17 ++++++
>>>>>>    .../ethernet/mellanox/mlx5/core/sh_devlink.c  | 61 
>>>>>> +++++++++++++++++++
>>>>>>    .../ethernet/mellanox/mlx5/core/sh_devlink.h  | 12 ++++
>>>>>>    include/linux/mlx5/driver.h                   |  1 +
>>>>>>    5 files changed, 94 insertions(+), 2 deletions(-)
>>>>>>    create mode 100644
>>>>>> drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>>>>>>    create mode 100644
>>>>>> drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>>>>>>
>>>>>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>>>>> b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>>>>> index 8ffa286a18f5..d39fe9c4a87c 100644
>>>>>> --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>>>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
>>>>>> @@ -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
>>>>>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>>>>> b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>>>>> index fdc3ba20912e..1c35c3fc3bb3 100644
>>>>>> --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>>>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>>>>> @@ -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
>>>>>> index 000000000000..bc33f95302df
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>>>>>> @@ -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
>>>>>> index 000000000000..8ab8d6940227
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.h
>>>>>> @@ -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__ */
>>>>>> diff --git a/include/linux/mlx5/driver.h 
>>>>>> b/include/linux/mlx5/driver.h
>>>>>> index 04dcd09f7517..1268fcf35ec7 100644
>>>>>> --- a/include/linux/mlx5/driver.h
>>>>>> +++ b/include/linux/mlx5/driver.h
>>>>>> @@ -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 {
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2026-03-24 19:58 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-12 10:03 [PATCH net-next v4 00/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
2026-03-12 10:03 ` [PATCH net-next v4 01/13] devlink: expose devlink instance index over netlink Jiri Pirko
2026-03-12 10:03 ` [PATCH net-next v4 02/13] devlink: add helpers to get bus_name/dev_name Jiri Pirko
2026-03-12 10:03 ` [PATCH net-next v4 03/13] devlink: avoid extra iterations when found devlink is not registered Jiri Pirko
2026-03-12 10:03 ` [PATCH net-next v4 04/13] devlink: allow to use devlink index as a command handle Jiri Pirko
2026-03-12 10:03 ` [PATCH net-next v4 05/13] devlink: support index-based lookup via bus_name/dev_name handle Jiri Pirko
2026-03-12 10:04 ` [PATCH net-next v4 06/13] devlink: support index-based notification filtering Jiri Pirko
2026-03-12 10:04 ` [PATCH net-next v4 07/13] devlink: introduce __devlink_alloc() with dev driver pointer Jiri Pirko
2026-03-12 10:04 ` [PATCH net-next v4 08/13] devlink: add devlink_dev_driver_name() helper and use it in trace events Jiri Pirko
2026-03-12 10:04 ` [PATCH net-next v4 09/13] devlink: add devl_warn() helper and use it in port warnings Jiri Pirko
2026-03-12 10:04 ` [PATCH net-next v4 10/13] devlink: allow devlink instance allocation without a backing device Jiri Pirko
2026-03-12 10:04 ` [PATCH net-next v4 11/13] devlink: introduce shared devlink instance for PFs on same chip Jiri Pirko
2026-03-12 10:04 ` [PATCH net-next v4 12/13] documentation: networking: add shared devlink documentation Jiri Pirko
2026-03-12 10:04 ` [PATCH net-next v4 13/13] net/mlx5: Add a shared devlink instance for PFs on same chip Jiri Pirko
2026-03-20 23:16   ` Adam Young
2026-03-20 23:37     ` Adam Young
2026-03-23 15:05       ` Jiri Pirko
2026-03-24 13:02         ` Jiri Pirko
2026-03-24 17:49           ` Adam Young
2026-03-24 19:57             ` Adam Young
2026-03-24 15:10   ` [PATCH net-next v4 13/15] " Ben Copeland
2026-03-24 15:21     ` Jiri Pirko
2026-03-24 15:37       ` Ben Copeland
2026-03-14 20:20 ` [PATCH net-next v4 00/13] devlink: introduce " patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox