Blob Blame History Raw
From: Leon Romanovsky <leonro@nvidia.com>
Date: Tue, 12 Oct 2021 16:15:24 +0300
Subject: devlink: Allow control devlink ops behavior through feature mask
Patch-mainline: v5.16-rc1
Git-commit: bd032e35c568ff7cfa347aa4ddd6491e2453f00c
References: jsc#SLE-19253

Introduce new devlink call to set feature mask to control devlink
behavior during device initialization phase after devlink_alloc()
is already called.

This allows us to set reload ops based on device property which
is not known at the beginning of driver initialization.

For the sake of simplicity, this API lacks any type of locking and
needs to be called before devlink_register() to make sure that no
parallel access to the ops is possible at this stage.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_devlink.c   |    1 
 drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_devlink.c |    1 
 drivers/net/ethernet/mellanox/mlx4/main.c                    |    1 
 drivers/net/ethernet/mellanox/mlx5/core/devlink.c            |    1 
 drivers/net/ethernet/mellanox/mlxsw/core.c                   |    1 
 drivers/net/netdevsim/dev.c                                  |    1 
 include/net/devlink.h                                        |    6 ++
 net/core/devlink.c                                           |   24 ++++++++++-
 8 files changed, 34 insertions(+), 2 deletions(-)

--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_devlink.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_devlink.c
@@ -119,6 +119,7 @@ int hclge_devlink_init(struct hclge_dev
 	priv->hdev = hdev;
 	hdev->devlink = devlink;
 
+	devlink_set_features(devlink, DEVLINK_F_RELOAD);
 	devlink_register(devlink);
 	devlink_reload_enable(devlink);
 	return 0;
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_devlink.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_devlink.c
@@ -121,6 +121,7 @@ int hclgevf_devlink_init(struct hclgevf_
 	priv->hdev = hdev;
 	hdev->devlink = devlink;
 
+	devlink_set_features(devlink, DEVLINK_F_RELOAD);
 	devlink_register(devlink);
 	devlink_reload_enable(devlink);
 	return 0;
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -4025,6 +4025,7 @@ static int mlx4_init_one(struct pci_dev
 		goto err_params_unregister;
 
 	pci_save_state(pdev);
+	devlink_set_features(devlink, DEVLINK_F_RELOAD);
 	devlink_register(devlink);
 	devlink_reload_enable(devlink);
 	return 0;
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -813,6 +813,7 @@ int mlx5_devlink_register(struct devlink
 	if (err)
 		goto traps_reg_err;
 
+	devlink_set_features(devlink, DEVLINK_F_RELOAD);
 	return 0;
 
 traps_reg_err:
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -2008,6 +2008,7 @@ __mlxsw_core_bus_device_register(const s
 	}
 
 	if (!reload) {
+		devlink_set_features(devlink, DEVLINK_F_RELOAD);
 		devlink_register(devlink);
 		devlink_reload_enable(devlink);
 	}
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -1511,6 +1511,7 @@ int nsim_dev_probe(struct nsim_bus_dev *
 		goto err_psample_exit;
 
 	nsim_dev->esw_mode = DEVLINK_ESWITCH_MODE_LEGACY;
+	devlink_set_features(devlink, DEVLINK_F_RELOAD);
 	devlink_register(devlink);
 	devlink_reload_enable(devlink);
 	return 0;
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -1186,6 +1186,11 @@ enum devlink_trap_group_generic_id {
 		.min_burst = _min_burst,				      \
 	}
 
+enum {
+	/* device supports reload operations */
+	DEVLINK_F_RELOAD = 1UL << 0,
+};
+
 struct devlink_ops {
 	/**
 	 * @supported_flash_update_params:
@@ -1503,6 +1508,7 @@ static inline struct devlink *devlink_al
 {
 	return devlink_alloc_ns(ops, priv_size, &init_net, dev);
 }
+void devlink_set_features(struct devlink *devlink, u64 features);
 void devlink_register(struct devlink *devlink);
 void devlink_unregister(struct devlink *devlink);
 void devlink_reload_enable(struct devlink *devlink);
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -54,6 +54,7 @@ struct devlink {
 	struct list_head trap_group_list;
 	struct list_head trap_policer_list;
 	const struct devlink_ops *ops;
+	u64 features;
 	struct xarray snapshot_ids;
 	struct devlink_dev_stats stats;
 	struct device *dev;
@@ -4032,7 +4033,7 @@ static int devlink_reload(struct devlink
 	struct net *curr_net;
 	int err;
 
-	if (!devlink->reload_enabled)
+	if (!devlink->reload_enabled || !(devlink->features & DEVLINK_F_RELOAD))
 		return -EOPNOTSUPP;
 
 	memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
@@ -8986,6 +8987,25 @@ static bool devlink_reload_actions_valid
 }
 
 /**
+ *	devlink_set_features - Set devlink supported features
+ *
+ *	@devlink: devlink
+ *	@features: devlink support features
+ *
+ *	This interface allows us to set reload ops separatelly from
+ *	the devlink_alloc.
+ */
+void devlink_set_features(struct devlink *devlink, u64 features)
+{
+	ASSERT_DEVLINK_NOT_REGISTERED(devlink);
+
+	WARN_ON(features & DEVLINK_F_RELOAD &&
+		!devlink_reload_supported(devlink->ops));
+	devlink->features = features;
+}
+EXPORT_SYMBOL_GPL(devlink_set_features);
+
+/**
  *	devlink_alloc_ns - Allocate new devlink instance resources
  *	in specific namespace
  *
@@ -9155,7 +9175,7 @@ void devlink_unregister(struct devlink *
 	wait_for_completion(&devlink->comp);
 
 	mutex_lock(&devlink_mutex);
-	WARN_ON(devlink_reload_supported(devlink->ops) &&
+	WARN_ON(devlink->features & DEVLINK_F_RELOAD &&
 		devlink->reload_enabled);
 	devlink_notify_unregister(devlink);
 	xa_clear_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);