public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] devlink, ice, mlx5: add init/fini ops for shared devlink for ice to use
@ 2026-04-28  9:09 Przemek Kitszel
  2026-04-28  9:09 ` [PATCH net-next 1/2] devlink, mlx5: add init/fini ops for shared devlink Przemek Kitszel
  2026-04-28  9:09 ` [PATCH net-next 2/2] ice: use shared devlink to store ice_adapters instead of custom xarray Przemek Kitszel
  0 siblings, 2 replies; 4+ messages in thread
From: Przemek Kitszel @ 2026-04-28  9:09 UTC (permalink / raw)
  To: netdev, Jakub Kicinski, Jiri Pirko
  Cc: intel-wired-lan, Tony Nguyen, Jacob Keller, Lukasz Czapnik,
	Jedrzej Jagielski, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Saeed Mahameed, Leon Romanovsky, Tariq Toukan,
	Mark Bloch, Simon Horman, Przemek Kitszel

Extend devlink by two callbacks used by shared devlink.
Callbacks provide option for the driver to have constructor/destructor
for the priv data attached to the shared devlink instance.

Use the callbacks from ice.
mlx5 is just touched to have additional param passed.

Non-null additional param for the constructor will be used by separate series.

Przemek Kitszel (2):
  devlink, mlx5: add init/fini ops for shared devlink
  ice: use shared devlink to store ice_adapters instead of custom xarray

 drivers/net/ethernet/intel/ice/ice_adapter.h  | 13 +--
 include/net/devlink.h                         | 26 +++++
 .../net/ethernet/intel/ice/devlink/devlink.c  |  3 +
 drivers/net/ethernet/intel/ice/ice_adapter.c  | 95 ++++++-------------
 drivers/net/ethernet/intel/ice/ice_main.c     |  4 +-
 .../ethernet/mellanox/mlx5/core/sh_devlink.c  |  2 +-
 net/devlink/sh_dev.c                          | 39 +++++++-
 7 files changed, 106 insertions(+), 76 deletions(-)

-- 
2.39.3


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

* [PATCH net-next 1/2] devlink, mlx5: add init/fini ops for shared devlink
  2026-04-28  9:09 [PATCH net-next 0/2] devlink, ice, mlx5: add init/fini ops for shared devlink for ice to use Przemek Kitszel
@ 2026-04-28  9:09 ` Przemek Kitszel
  2026-04-28 11:10   ` Jiri Pirko
  2026-04-28  9:09 ` [PATCH net-next 2/2] ice: use shared devlink to store ice_adapters instead of custom xarray Przemek Kitszel
  1 sibling, 1 reply; 4+ messages in thread
From: Przemek Kitszel @ 2026-04-28  9:09 UTC (permalink / raw)
  To: netdev, Jakub Kicinski, Jiri Pirko
  Cc: intel-wired-lan, Tony Nguyen, Jacob Keller, Lukasz Czapnik,
	Jedrzej Jagielski, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Saeed Mahameed, Leon Romanovsky, Tariq Toukan,
	Mark Bloch, Simon Horman, Przemek Kitszel, Aleksandr Loktionov

Add .shd_init() and .shd_fini() ops, that will be called for the first
devlink_shd_get() (to initialize driver' priv data) and on the last
devlink_shd_put() (to allow for the cleanup). Both ops are optional.

.shd_init() could return an error, which will stop creation of shd
instance. The initializer also gets an additional, optional param,
that driver could use for any needs.

If any of the callbacks will need to get devlink instance, it could
be accessed by shd_priv_to_devlink().

Both callbacks are called with devl_lock held and devlink registered.

Next commit will make use of the callbacks, another one will make use also
of the non-null additional param (outside of this series).

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
---
first discussed at:
https://lore.kernel.org/netdev/20260325063143.261806-3-przemyslaw.kitszel@intel.com

Sashiko suggested to convert devlink_shd_create() to return ERR_PTR(),
and propagate that up to the driver. It think it will just make code more
verbose for not much benefit. And drivers could just store err if they
want in the passed @init_param.

---
 include/net/devlink.h                         | 26 +++++++++++++
 .../ethernet/mellanox/mlx5/core/sh_devlink.c  |  2 +-
 net/devlink/sh_dev.c                          | 39 ++++++++++++++++++-
 3 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index bcd31de1f890..5d3a1337bfa1 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -1586,6 +1586,30 @@ struct devlink_ops {
 				    struct devlink_rate *parent,
 				    void *priv_child, void *priv_parent,
 				    struct netlink_ext_ack *extack);
+
+	/**
+	 * shd_init: Shared devlink instance initializer
+	 * @priv: shd_devlink' priv
+	 * @init_param: additional param to pass to driver callback
+	 *
+	 * Called once when the shared instance is first created (by the first
+	 * devlink_shd_get() call).
+	 * Should initialize the driver's private data embedded in the shared
+	 * devlink. May be NULL.
+	 *
+	 * Return: 0 on success, negative to prevent shared instance usage.
+	 */
+	int (*shd_init)(void *priv, void *init_param);
+	/**
+	 * shd_fini: Shared devlink instance finalizer
+	 * @priv: shd_devlink' priv
+	 *
+	 * Called once when the last reference is dropped and the shared
+	 * instance is destroyed. Should clean up the driver's private data.
+	 * May be NULL.
+	 */
+	void (*shd_fini)(void *priv);
+
 	/**
 	 * selftests_check() - queries if selftest is supported
 	 * @devlink: devlink instance
@@ -1651,9 +1675,11 @@ void devlink_free(struct devlink *devlink);
 struct devlink *devlink_shd_get(const char *id,
 				const struct devlink_ops *ops,
 				size_t priv_size,
+				void *init_param,
 				const struct device_driver *driver);
 void devlink_shd_put(struct devlink *devlink);
 void *devlink_shd_get_priv(struct devlink *devlink);
+struct devlink *shd_priv_to_devlink(void *priv);
 
 /**
  * struct devlink_port_ops - Port operations
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
index b925364765ac..1b8b1ce7e72d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
@@ -43,7 +43,7 @@ int mlx5_shd_init(struct mlx5_core_dev *dev)
 	*end = '\0';
 
 	/* Get or create shared devlink instance */
-	devlink = devlink_shd_get(sn, &mlx5_shd_ops, 0, pdev->dev.driver);
+	devlink = devlink_shd_get(sn, &mlx5_shd_ops, 0, NULL, pdev->dev.driver);
 	kfree(sn);
 	if (!devlink)
 		return -ENOMEM;
diff --git a/net/devlink/sh_dev.c b/net/devlink/sh_dev.c
index 85acce97e788..048a2a6adc9e 100644
--- a/net/devlink/sh_dev.c
+++ b/net/devlink/sh_dev.c
@@ -34,6 +34,7 @@ static struct devlink_shd *devlink_shd_lookup(const char *id)
 static struct devlink_shd *devlink_shd_create(const char *id,
 					      const struct devlink_ops *ops,
 					      size_t priv_size,
+					      void *init_param,
 					      const struct device_driver *driver)
 {
 	struct devlink_shd *shd;
@@ -49,16 +50,30 @@ static struct devlink_shd *devlink_shd_create(const char *id,
 	if (!shd->id)
 		goto err_devlink_free;
 	shd->priv_size = priv_size;
-	refcount_set(&shd->refcount, 1);
 
 	devl_lock(devlink);
 	devl_register(devlink);
+
+	if (ops->shd_init) {
+		int err;
+
+		err = ops->shd_init(shd->priv, init_param);
+		if (err)
+			goto err_unregister;
+	}
+
 	devl_unlock(devlink);
 
+	refcount_set(&shd->refcount, 1);
 	list_add_tail(&shd->list, &shd_list);
 
 	return shd;
 
+err_unregister:
+	devl_unregister(devlink);
+	devl_unlock(devlink);
+	kfree(shd->id);
+
 err_devlink_free:
 	devlink_free(devlink);
 	return NULL;
@@ -69,7 +84,12 @@ static void devlink_shd_destroy(struct devlink_shd *shd)
 	struct devlink *devlink = priv_to_devlink(shd);
 
 	list_del(&shd->list);
+
 	devl_lock(devlink);
+
+	if (devlink->ops->shd_fini)
+		devlink->ops->shd_fini(shd->priv);
+
 	devl_unregister(devlink);
 	devl_unlock(devlink);
 	kfree(shd->id);
@@ -81,6 +101,7 @@ static void devlink_shd_destroy(struct devlink_shd *shd)
  * @id: Identifier string (e.g., serial number) for the shared instance
  * @ops: Devlink operations structure
  * @priv_size: Size of private data structure
+ * @init_param: Passed to .shd_init() callback alongside driver's priv
  * @driver: Driver associated with the shared devlink instance
  *
  * Get an existing shared devlink instance identified by @id, or create
@@ -96,16 +117,17 @@ static void devlink_shd_destroy(struct devlink_shd *shd)
 struct devlink *devlink_shd_get(const char *id,
 				const struct devlink_ops *ops,
 				size_t priv_size,
+				void *init_param,
 				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);
+		shd = devlink_shd_create(id, ops, priv_size, init_param, driver);
 		goto unlock;
 	}
 
@@ -159,3 +181,16 @@ void *devlink_shd_get_priv(struct devlink *devlink)
 	return shd->priv;
 }
 EXPORT_SYMBOL_GPL(devlink_shd_get_priv);
+
+/** shd_priv_to_devlink - Get devlink instance from shd_devlink's priv
+ * @priv: Driver's priv data
+ *
+ * Return: pointer to shared devlink instance the @priv belongs to.
+ */
+struct devlink *shd_priv_to_devlink(void *priv)
+{
+	struct devlink_shd *shd = container_of(priv, struct devlink_shd, priv);
+
+	return priv_to_devlink(shd);
+}
+EXPORT_SYMBOL_GPL(shd_priv_to_devlink);
-- 
2.39.3


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

* [PATCH net-next 2/2] ice: use shared devlink to store ice_adapters instead of custom xarray
  2026-04-28  9:09 [PATCH net-next 0/2] devlink, ice, mlx5: add init/fini ops for shared devlink for ice to use Przemek Kitszel
  2026-04-28  9:09 ` [PATCH net-next 1/2] devlink, mlx5: add init/fini ops for shared devlink Przemek Kitszel
@ 2026-04-28  9:09 ` Przemek Kitszel
  1 sibling, 0 replies; 4+ messages in thread
From: Przemek Kitszel @ 2026-04-28  9:09 UTC (permalink / raw)
  To: netdev, Jakub Kicinski, Jiri Pirko
  Cc: intel-wired-lan, Tony Nguyen, Jacob Keller, Lukasz Czapnik,
	Jedrzej Jagielski, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Saeed Mahameed, Leon Romanovsky, Tariq Toukan,
	Mark Bloch, Simon Horman, Przemek Kitszel, Aleksandr Loktionov,
	Sergey Temerkhanov

Refactor our storage and deduplication logic of ice_adapters by moving
it to be handled by shared devlink instance, recently added by
Jiri Pirko [1].

We wanted the devlink instance for whole device anyway - later in the
series I will add devlink resources under it.

Make the shared devlink a parent (wrt. nesting) of the actual PF devices.

[1] commit 411ad0605875 ("Merge branch 'devlink-introduce-shared-devlink-instance-for-pfs-on-same-chip'")
[1]  https://lore.kernel.org/all/20260312100407.551173-1-jiri@resnulli.us
Reviewed-by: Jedrzej Jagielski <jedrzej.jagielski@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
---
CC: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_adapter.h  | 13 +--
 .../net/ethernet/intel/ice/devlink/devlink.c  |  3 +
 drivers/net/ethernet/intel/ice/ice_adapter.c  | 95 ++++++-------------
 drivers/net/ethernet/intel/ice/ice_main.c     |  4 +-
 4 files changed, 42 insertions(+), 73 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h
index e95266c7f20b..d4ec7e78abb4 100644
--- a/drivers/net/ethernet/intel/ice/ice_adapter.h
+++ b/drivers/net/ethernet/intel/ice/ice_adapter.h
@@ -6,7 +6,8 @@
 
 #include <linux/types.h>
 #include <linux/spinlock_types.h>
-#include <linux/refcount_types.h>
+
+#include <net/devlink.h>
 
 struct pci_dev;
 struct ice_pf;
@@ -27,27 +28,26 @@ struct ice_port_list {
 
 /**
  * struct ice_adapter - PCI adapter resources shared across PFs
- * @refcount: Reference count. struct ice_pf objects hold the references.
+ * @devlink: ice adapter's devlink (whole dev devlink)
  * @ptp_gltsyn_time_lock: Spinlock protecting access to the GLTSYN_TIME
  *                        register of the PTP clock.
  * @txq_ctx_lock: Spinlock protecting access to the GLCOMM_QTX_CNTX_CTL register
  * @ctrl_pf: Control PF of the adapter
  * @ports: Ports list
- * @index: 64-bit index cached for collision detection on 32bit systems
  */
 struct ice_adapter {
-	refcount_t refcount;
+	struct devlink *devlink;
+
 	/* For access to the GLTSYN_TIME register */
 	spinlock_t ptp_gltsyn_time_lock;
 	/* For access to GLCOMM_QTX_CNTX_CTL register */
 	spinlock_t txq_ctx_lock;
 
 	struct ice_pf *ctrl_pf;
 	struct ice_port_list ports;
-	u64 index;
 };
 
 struct ice_adapter *ice_adapter_get(struct pci_dev *pdev);
-void ice_adapter_put(struct pci_dev *pdev);
+void ice_adapter_put(struct ice_adapter *adapter);
 
 #endif /* _ICE_ADAPTER_H */
diff --git a/drivers/net/ethernet/intel/ice/devlink/devlink.c b/drivers/net/ethernet/intel/ice/devlink/devlink.c
index 641d6e289d5c..f6382d038048 100644
--- a/drivers/net/ethernet/intel/ice/devlink/devlink.c
+++ b/drivers/net/ethernet/intel/ice/devlink/devlink.c
@@ -1750,7 +1750,10 @@ struct ice_sf_priv *ice_allocate_sf(struct device *dev, struct ice_pf *pf)
 void ice_devlink_register(struct ice_pf *pf)
 {
 	struct devlink *devlink = priv_to_devlink(pf);
+	struct ice_adapter *adapter = pf->adapter;
 
+	if (adapter)
+		devl_nested_devlink_set(adapter->devlink, devlink);
 	devl_register(devlink);
 }
 
diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.c b/drivers/net/ethernet/intel/ice/ice_adapter.c
index cbb57060bd56..8ec1b600905f 100644
--- a/drivers/net/ethernet/intel/ice/ice_adapter.c
+++ b/drivers/net/ethernet/intel/ice/ice_adapter.c
@@ -1,18 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-FileCopyrightText: Copyright Red Hat
 
-#include <linux/cleanup.h>
-#include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/xarray.h>
+
 #include "ice_adapter.h"
 #include "ice.h"
 
-static DEFINE_XARRAY(ice_adapters);
-static DEFINE_MUTEX(ice_adapters_mutex);
-
 #define ICE_ADAPTER_FIXED_INDEX	BIT_ULL(63)
 
 #define ICE_ADAPTER_INDEX_E825C	\
@@ -40,44 +35,36 @@ static u64 ice_adapter_index(struct pci_dev *pdev)
 	}
 }
 
-static unsigned long ice_adapter_xa_index(struct pci_dev *pdev)
-{
-	u64 index = ice_adapter_index(pdev);
-
-#if BITS_PER_LONG == 64
-	return index;
-#else
-	return (u32)index ^ (u32)(index >> 32);
-#endif
-}
-
-static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev)
+static int ice_adapter_init(void *priv, void *init_param)
 {
-	struct ice_adapter *adapter;
+	struct ice_adapter *adapter = priv;
+	struct devlink *devlink;
 
-	adapter = kzalloc_obj(*adapter);
-	if (!adapter)
-		return NULL;
+	devlink = shd_priv_to_devlink(adapter);
+	adapter->devlink = devlink;
 
-	adapter->index = ice_adapter_index(pdev);
 	spin_lock_init(&adapter->ptp_gltsyn_time_lock);
 	spin_lock_init(&adapter->txq_ctx_lock);
-	refcount_set(&adapter->refcount, 1);
 
 	mutex_init(&adapter->ports.lock);
 	INIT_LIST_HEAD(&adapter->ports.ports);
 
-	return adapter;
+	return 0;
 }
 
-static void ice_adapter_free(struct ice_adapter *adapter)
+static void ice_adapter_fini(void *priv)
 {
+	struct ice_adapter *adapter = priv;
+
 	WARN_ON(!list_empty(&adapter->ports.ports));
 	mutex_destroy(&adapter->ports.lock);
-
-	kfree(adapter);
 }
 
+static const struct devlink_ops ice_adapter_devlink_ops = {
+	.shd_init = ice_adapter_init,
+	.shd_fini = ice_adapter_fini,
+};
+
 /**
  * ice_adapter_get - Get a shared ice_adapter structure.
  * @pdev: Pointer to the pci_dev whose driver is getting the ice_adapter.
@@ -94,28 +81,19 @@ static void ice_adapter_free(struct ice_adapter *adapter)
 struct ice_adapter *ice_adapter_get(struct pci_dev *pdev)
 {
 	struct ice_adapter *adapter;
-	unsigned long index;
-	int err;
-
-	index = ice_adapter_xa_index(pdev);
-	scoped_guard(mutex, &ice_adapters_mutex) {
-		adapter = xa_load(&ice_adapters, index);
-		if (adapter) {
-			refcount_inc(&adapter->refcount);
-			WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev));
-			return adapter;
-		}
-		err = xa_reserve(&ice_adapters, index, GFP_KERNEL);
-		if (err)
-			return ERR_PTR(err);
-
-		adapter = ice_adapter_new(pdev);
-		if (!adapter) {
-			xa_release(&ice_adapters, index);
-			return ERR_PTR(-ENOMEM);
-		}
-		xa_store(&ice_adapters, index, adapter, GFP_KERNEL);
-	}
+	struct devlink *devlink;
+	char devlink_id[32];
+	u64 index;
+
+	index = ice_adapter_index(pdev);
+	snprintf(devlink_id, sizeof(devlink_id), "%llx", index);
+	devlink = devlink_shd_get(devlink_id, &ice_adapter_devlink_ops,
+				  sizeof(*adapter), NULL, pdev->dev.driver);
+	if (!devlink)
+		return ERR_PTR(-ENOMEM);
+
+	adapter = devlink_shd_get_priv(devlink);
+
 	return adapter;
 }
 
@@ -128,20 +106,7 @@ struct ice_adapter *ice_adapter_get(struct pci_dev *pdev)
  *
  * Context: Process, may sleep.
  */
-void ice_adapter_put(struct pci_dev *pdev)
+void ice_adapter_put(struct ice_adapter *adapter)
 {
-	struct ice_adapter *adapter;
-	unsigned long index;
-
-	index = ice_adapter_xa_index(pdev);
-	scoped_guard(mutex, &ice_adapters_mutex) {
-		adapter = xa_load(&ice_adapters, index);
-		if (WARN_ON(!adapter))
-			return;
-		if (!refcount_dec_and_test(&adapter->refcount))
-			return;
-
-		WARN_ON(xa_erase(&ice_adapters, index) != adapter);
-	}
-	ice_adapter_free(adapter);
+	devlink_shd_put(adapter->devlink);
 }
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 6ebaa41127a4..6e257ad13bd1 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5349,7 +5349,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
 unroll_dev_init:
 	need_dev_deinit = true;
 unroll_adapter:
-	ice_adapter_put(pdev);
+	ice_adapter_put(adapter);
 unroll_hw_init:
 	ice_deinit_hw(hw);
 	if (need_dev_deinit)
@@ -5462,7 +5462,7 @@ static void ice_remove(struct pci_dev *pdev)
 	ice_setup_mc_magic_wake(pf);
 	ice_set_wake(pf);
 
-	ice_adapter_put(pdev);
+	ice_adapter_put(pf->adapter);
 	ice_deinit_hw(&pf->hw);
 
 	ice_deinit_dev(pf);
-- 
2.39.3


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

* Re: [PATCH net-next 1/2] devlink, mlx5: add init/fini ops for shared devlink
  2026-04-28  9:09 ` [PATCH net-next 1/2] devlink, mlx5: add init/fini ops for shared devlink Przemek Kitszel
@ 2026-04-28 11:10   ` Jiri Pirko
  0 siblings, 0 replies; 4+ messages in thread
From: Jiri Pirko @ 2026-04-28 11:10 UTC (permalink / raw)
  To: Przemek Kitszel
  Cc: netdev, Jakub Kicinski, intel-wired-lan, Tony Nguyen,
	Jacob Keller, Lukasz Czapnik, Jedrzej Jagielski, Andrew Lunn,
	David S. Miller, Eric Dumazet, Paolo Abeni, Saeed Mahameed,
	Leon Romanovsky, Tariq Toukan, Mark Bloch, Simon Horman,
	Aleksandr Loktionov

Tue, Apr 28, 2026 at 11:09:11AM +0200, przemyslaw.kitszel@intel.com wrote:
>Add .shd_init() and .shd_fini() ops, that will be called for the first
>devlink_shd_get() (to initialize driver' priv data) and on the last
>devlink_shd_put() (to allow for the cleanup). Both ops are optional.
>
>.shd_init() could return an error, which will stop creation of shd
>instance. The initializer also gets an additional, optional param,
>that driver could use for any needs.
>
>If any of the callbacks will need to get devlink instance, it could
>be accessed by shd_priv_to_devlink().
>
>Both callbacks are called with devl_lock held and devlink registered.
>
>Next commit will make use of the callbacks, another one will make use also
>of the non-null additional param (outside of this series).
>
>Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
>Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
>---
>first discussed at:
>https://lore.kernel.org/netdev/20260325063143.261806-3-przemyslaw.kitszel@intel.com
>
>Sashiko suggested to convert devlink_shd_create() to return ERR_PTR(),
>and propagate that up to the driver. It think it will just make code more
>verbose for not much benefit. And drivers could just store err if they
>want in the passed @init_param.
>
>---
> include/net/devlink.h                         | 26 +++++++++++++
> .../ethernet/mellanox/mlx5/core/sh_devlink.c  |  2 +-
> net/devlink/sh_dev.c                          | 39 ++++++++++++++++++-
> 3 files changed, 64 insertions(+), 3 deletions(-)
>
>diff --git a/include/net/devlink.h b/include/net/devlink.h
>index bcd31de1f890..5d3a1337bfa1 100644
>--- a/include/net/devlink.h
>+++ b/include/net/devlink.h
>@@ -1586,6 +1586,30 @@ struct devlink_ops {
> 				    struct devlink_rate *parent,
> 				    void *priv_child, void *priv_parent,
> 				    struct netlink_ext_ack *extack);
>+
>+	/**
>+	 * shd_init: Shared devlink instance initializer
>+	 * @priv: shd_devlink' priv
>+	 * @init_param: additional param to pass to driver callback
>+	 *
>+	 * Called once when the shared instance is first created (by the first
>+	 * devlink_shd_get() call).
>+	 * Should initialize the driver's private data embedded in the shared
>+	 * devlink. May be NULL.
>+	 *
>+	 * Return: 0 on success, negative to prevent shared instance usage.
>+	 */
>+	int (*shd_init)(void *priv, void *init_param);

1. "param" has specific meaning in devlink context
2. You don't use the arg in driver

Care to drop it?

Otherwise, this looks fine to me. Thanks! (small nitpick below)


>+	/**
>+	 * shd_fini: Shared devlink instance finalizer
>+	 * @priv: shd_devlink' priv
>+	 *
>+	 * Called once when the last reference is dropped and the shared
>+	 * instance is destroyed. Should clean up the driver's private data.
>+	 * May be NULL.
>+	 */
>+	void (*shd_fini)(void *priv);
>+
> 	/**
> 	 * selftests_check() - queries if selftest is supported
> 	 * @devlink: devlink instance
>@@ -1651,9 +1675,11 @@ void devlink_free(struct devlink *devlink);
> struct devlink *devlink_shd_get(const char *id,
> 				const struct devlink_ops *ops,
> 				size_t priv_size,
>+				void *init_param,
> 				const struct device_driver *driver);
> void devlink_shd_put(struct devlink *devlink);
> void *devlink_shd_get_priv(struct devlink *devlink);
>+struct devlink *shd_priv_to_devlink(void *priv);
> 
> /**
>  * struct devlink_port_ops - Port operations
>diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>index b925364765ac..1b8b1ce7e72d 100644
>--- a/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>+++ b/drivers/net/ethernet/mellanox/mlx5/core/sh_devlink.c
>@@ -43,7 +43,7 @@ int mlx5_shd_init(struct mlx5_core_dev *dev)
> 	*end = '\0';
> 
> 	/* Get or create shared devlink instance */
>-	devlink = devlink_shd_get(sn, &mlx5_shd_ops, 0, pdev->dev.driver);
>+	devlink = devlink_shd_get(sn, &mlx5_shd_ops, 0, NULL, pdev->dev.driver);
> 	kfree(sn);
> 	if (!devlink)
> 		return -ENOMEM;
>diff --git a/net/devlink/sh_dev.c b/net/devlink/sh_dev.c
>index 85acce97e788..048a2a6adc9e 100644
>--- a/net/devlink/sh_dev.c
>+++ b/net/devlink/sh_dev.c
>@@ -34,6 +34,7 @@ static struct devlink_shd *devlink_shd_lookup(const char *id)
> static struct devlink_shd *devlink_shd_create(const char *id,
> 					      const struct devlink_ops *ops,
> 					      size_t priv_size,
>+					      void *init_param,
> 					      const struct device_driver *driver)
> {
> 	struct devlink_shd *shd;
>@@ -49,16 +50,30 @@ static struct devlink_shd *devlink_shd_create(const char *id,
> 	if (!shd->id)
> 		goto err_devlink_free;
> 	shd->priv_size = priv_size;
>-	refcount_set(&shd->refcount, 1);
> 
> 	devl_lock(devlink);
> 	devl_register(devlink);
>+
>+	if (ops->shd_init) {
>+		int err;
>+
>+		err = ops->shd_init(shd->priv, init_param);
>+		if (err)
>+			goto err_unregister;
>+	}
>+
> 	devl_unlock(devlink);
> 
>+	refcount_set(&shd->refcount, 1);
> 	list_add_tail(&shd->list, &shd_list);
> 
> 	return shd;
> 
>+err_unregister:
>+	devl_unregister(devlink);
>+	devl_unlock(devlink);
>+	kfree(shd->id);
>+
> err_devlink_free:
> 	devlink_free(devlink);
> 	return NULL;
>@@ -69,7 +84,12 @@ static void devlink_shd_destroy(struct devlink_shd *shd)
> 	struct devlink *devlink = priv_to_devlink(shd);
> 
> 	list_del(&shd->list);
>+

Not sure why to add empty line here.


> 	devl_lock(devlink);
>+
>+	if (devlink->ops->shd_fini)
>+		devlink->ops->shd_fini(shd->priv);
>+
> 	devl_unregister(devlink);
> 	devl_unlock(devlink);
> 	kfree(shd->id);
>@@ -81,6 +101,7 @@ static void devlink_shd_destroy(struct devlink_shd *shd)
>  * @id: Identifier string (e.g., serial number) for the shared instance
>  * @ops: Devlink operations structure
>  * @priv_size: Size of private data structure
>+ * @init_param: Passed to .shd_init() callback alongside driver's priv
>  * @driver: Driver associated with the shared devlink instance
>  *
>  * Get an existing shared devlink instance identified by @id, or create
>@@ -96,16 +117,17 @@ static void devlink_shd_destroy(struct devlink_shd *shd)
> struct devlink *devlink_shd_get(const char *id,
> 				const struct devlink_ops *ops,
> 				size_t priv_size,
>+				void *init_param,
> 				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);
>+		shd = devlink_shd_create(id, ops, priv_size, init_param, driver);
> 		goto unlock;
> 	}
> 
>@@ -159,3 +181,16 @@ void *devlink_shd_get_priv(struct devlink *devlink)
> 	return shd->priv;
> }
> EXPORT_SYMBOL_GPL(devlink_shd_get_priv);
>+
>+/** shd_priv_to_devlink - Get devlink instance from shd_devlink's priv
>+ * @priv: Driver's priv data
>+ *
>+ * Return: pointer to shared devlink instance the @priv belongs to.
>+ */
>+struct devlink *shd_priv_to_devlink(void *priv)
>+{
>+	struct devlink_shd *shd = container_of(priv, struct devlink_shd, priv);
>+
>+	return priv_to_devlink(shd);
>+}
>+EXPORT_SYMBOL_GPL(shd_priv_to_devlink);
>-- 
>2.39.3
>

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

end of thread, other threads:[~2026-04-28 11:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28  9:09 [PATCH net-next 0/2] devlink, ice, mlx5: add init/fini ops for shared devlink for ice to use Przemek Kitszel
2026-04-28  9:09 ` [PATCH net-next 1/2] devlink, mlx5: add init/fini ops for shared devlink Przemek Kitszel
2026-04-28 11:10   ` Jiri Pirko
2026-04-28  9:09 ` [PATCH net-next 2/2] ice: use shared devlink to store ice_adapters instead of custom xarray Przemek Kitszel

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