[PATCH net-next 07/14] devlink: Implement port params registration

Saeed Mahameed
2025-02-28T02:13:30Z

From: Saeed Mahameed <saeedm@nvidia.com>

Port params infrastructure is incomplete and needs a bit of plumbing to
support port params commands from netlink.

Introduce port params registration API, very similar to current devlink
params API, add the params xarray to devlink_port structure and
decouple devlink params registration routines from the devlink
structure.

Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
include/net/devlink.h | 14 ++++
net/devlink/param.c | 150 ++++++++++++++++++++++++++++++++++--------
net/devlink/port.c | 3 +
3 files changed, 140 insertions(+), 27 deletions(-)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index eed1e4507d17..11f98e3a750b 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -125,6 +125,7 @@ struct devlink_port {
struct list_head region_list;
struct devlink *devlink;
const struct devlink_port_ops *ops;
+ struct xarray params;
unsigned int index;
spinlock_t type_lock; /* Protects type and type_eth/ib
* structures consistency.
@@ -1823,6 +1824,19 @@ void devl_params_unregister(struct devlink *devlink,
void devlink_params_unregister(struct devlink *devlink,
const struct devlink_param *params,
size_t params_count);
+int devl_port_params_register(struct devlink_port *devlink_port,
+ const struct devlink_param *params,
+ size_t params_count);
+int devlink_port_params_register(struct devlink_port *devlink_port,
+ const struct devlink_param *params,
+ size_t params_count);
+void devl_port_params_unregister(struct devlink_port *devlink_port,
+ const struct devlink_param *params,
+ size_t params_count);
+void devlink_port_params_unregister(struct devlink_port *devlink_port,
+ const struct devlink_param *params,
+ size_t params_count);
+
int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
union devlink_param_value *val);
void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
diff --git a/net/devlink/param.c b/net/devlink/param.c
index 2263aba85a79..719eeb5152c3 100644
--- a/net/devlink/param.c
+++ b/net/devlink/param.c
@@ -627,13 +627,16 @@ static int devlink_param_verify(const struct devlink_param *param)
}

static int devlink_param_register(struct devlink *devlink,
+ struct devlink_port *devlink_port,
+ struct xarray *params_arr,
const struct devlink_param *param)
{
struct devlink_param_item *param_item;
+ enum devlink_command cmd;
int err;

WARN_ON(devlink_param_verify(param));
- WARN_ON(devlink_param_find_by_name(&devlink->params, param->name));
+ WARN_ON(devlink_param_find_by_name(params_arr, param->name));

if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
WARN_ON(param->get || param->set);
@@ -646,11 +649,13 @@ static int devlink_param_register(struct devlink *devlink,

param_item->param = param;

- err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL);
+ err = xa_insert(params_arr, param->id, param_item, GFP_KERNEL);
if (err)
goto err_xa_insert;

- devlink_param_notify(devlink, NULL, param_item, DEVLINK_CMD_PARAM_NEW);
+ cmd = devlink_port ? DEVLINK_CMD_PORT_PARAM_NEW : DEVLINK_CMD_PARAM_NEW;
+ devlink_param_notify(devlink, devlink_port, param_item, cmd);
+
return 0;

err_xa_insert:
@@ -659,30 +664,28 @@ static int devlink_param_register(struct devlink *devlink,
}

static void devlink_param_unregister(struct devlink *devlink,
+ struct devlink_port *devlink_port,
+ struct xarray *params_arr,
const struct devlink_param *param)
{
struct devlink_param_item *param_item;
+ enum devlink_command cmd;

- param_item = devlink_param_find_by_id(&devlink->params, param->id);
+ param_item = devlink_param_find_by_id(params_arr, param->id);
if (WARN_ON(!param_item))
return;
- devlink_param_notify(devlink, NULL, param_item, DEVLINK_CMD_PARAM_DEL);
- xa_erase(&devlink->params, param->id);
+
+ cmd = devlink_port ? DEVLINK_CMD_PORT_PARAM_DEL : DEVLINK_CMD_PARAM_DEL;
+ devlink_param_notify(devlink, devlink_port, param_item, cmd);
+ xa_erase(params_arr, param->id);
kfree(param_item);
}

-/**
- * devl_params_register - register configuration parameters
- *
- * @devlink: devlink
- * @params: configuration parameters array
- * @params_count: number of parameters provided
- *
- * Register the configuration parameters supported by the driver.
- */
-int devl_params_register(struct devlink *devlink,
- const struct devlink_param *params,
- size_t params_count)
+static int __devlink_params_register(struct devlink *devlink,
+ struct devlink_port *devlink_port,
+ struct xarray *params_arr,
+ const struct devlink_param *params,
+ size_t params_count)
{
const struct devlink_param *param = params;
int i, err;
@@ -690,10 +693,12 @@ int devl_params_register(struct devlink *devlink,
lockdep_assert_held(&devlink->lock);

for (i = 0; i < params_count; i++, param++) {
- err = devlink_param_register(devlink, param);
+ err = devlink_param_register(devlink, devlink_port, params_arr,
+ param);
if (err)
goto rollback;
}
+
return 0;

rollback:
@@ -701,9 +706,28 @@ int devl_params_register(struct devlink *devlink,
return err;

for (param--; i > 0; i--, param--)
- devlink_param_unregister(devlink, param);
+ devlink_param_unregister(devlink, devlink_port, params_arr,
+ param);
+
return err;
}
+
+/**
+ * devl_params_register - register configuration parameters
+ *
+ * @devlink: devlink
+ * @params: configuration parameters array
+ * @params_count: number of parameters provided
+ *
+ * Register the configuration parameters supported by the driver.
+ */
+int devl_params_register(struct devlink *devlink,
+ const struct devlink_param *params,
+ size_t params_count)
+{
+ return __devlink_params_register(devlink, NULL, &devlink->params,
+ params, params_count);
+}
EXPORT_SYMBOL_GPL(devl_params_register);

int devlink_params_register(struct devlink *devlink,
@@ -719,6 +743,22 @@ int devlink_params_register(struct devlink *devlink,
}
EXPORT_SYMBOL_GPL(devlink_params_register);

+static void __devlink_params_unregister(struct devlink *devlink,
+ struct devlink_port *devlink_port,
+ struct xarray *params_arr,
+ const struct devlink_param *params,
+ size_t params_count)
+{
+ const struct devlink_param *param = params;
+ int i;
+
+ lockdep_assert_held(&devlink->lock);
+
+ for (i = 0; i < params_count; i++, param++)
+ devlink_param_unregister(devlink, devlink_port, params_arr,
+ param);
+}
+
/**
* devl_params_unregister - unregister configuration parameters
* @devlink: devlink
@@ -729,13 +769,8 @@ void devl_params_unregister(struct devlink *devlink,
const struct devlink_param *params,
size_t params_count)
{
- const struct devlink_param *param = params;
- int i;
-
- lockdep_assert_held(&devlink->lock);
-
- for (i = 0; i < params_count; i++, param++)
- devlink_param_unregister(devlink, param);
+ __devlink_params_unregister(devlink, NULL, &devlink->params,
+ params, params_count);
}
EXPORT_SYMBOL_GPL(devl_params_unregister);

@@ -749,6 +784,67 @@ void devlink_params_unregister(struct devlink *devlink,
}
EXPORT_SYMBOL_GPL(devlink_params_unregister);

+/**
+ * devl_port_params_register - register configuration parameters for port
+ *
+ * @devlink_port: devlink port
+ * @params: configuration parameters array
+ * @params_count: number of parameters provided
+ *
+ * Register the configuration parameters supported by the driver for the
+ * specific port.
+ */
+int devl_port_params_register(struct devlink_port *devlink_port,
+ const struct devlink_param *params,
+ size_t params_count)
+{
+ return __devlink_params_register(devlink_port->devlink,
+ devlink_port,
+ &devlink_port->params,
+ params, params_count);
+}
+EXPORT_SYMBOL_GPL(devl_port_params_register);
+
+/**
+ * devl_port_params_unregister - unregister configuration parameters for port
+ *
+ * @devlink_port: devlink port
+ * @params: configuration parameters to unregister
+ * @params_count: number of parameters provided
+ */
+void devl_port_params_unregister(struct devlink_port *devlink_port,
+ const struct devlink_param *params,
+ size_t params_count)
+{
+ __devlink_params_unregister(devlink_port->devlink, devlink_port,
+ &devlink_port->params,
+ params, params_count);
+}
+EXPORT_SYMBOL_GPL(devl_port_params_unregister);
+
+int devlink_port_params_register(struct devlink_port *devlink_port,
+ const struct devlink_param *params,
+ size_t params_count)
+{
+ int err;
+
+ devl_lock(devlink_port->devlink);
+ err = devl_port_params_register(devlink_port, params, params_count);
+ devl_unlock(devlink_port->devlink);
+ return err;
+}
+EXPORT_SYMBOL_GPL(devlink_port_params_register);
+
+void devlink_port_params_unregister(struct devlink_port *devlink_port,
+ const struct devlink_param *params,
+ size_t params_count)
+{
+ devl_lock(devlink_port->devlink);
+ devl_port_params_unregister(devlink_port, params, params_count);
+ devl_unlock(devlink_port->devlink);
+}
+EXPORT_SYMBOL_GPL(devlink_port_params_unregister);
+
/**
* devl_param_driverinit_value_get - get configuration parameter
* value for driver initializing
diff --git a/net/devlink/port.c b/net/devlink/port.c
index 939081a0e615..39bba3f7a1f9 100644
--- a/net/devlink/port.c
+++ b/net/devlink/port.c
@@ -1075,6 +1075,8 @@ int devl_port_register_with_ops(struct devlink *devlink,
devlink_port->registered = true;
devlink_port->index = port_index;
devlink_port->ops = ops ? ops : &devlink_port_dummy_ops;
+ xa_init_flags(&devlink_port->params, XA_FLAGS_ALLOC);
+
spin_lock_init(&devlink_port->type_lock);
INIT_LIST_HEAD(&devlink_port->reporter_list);
err = xa_insert(&devlink->ports, port_index, devlink_port, GFP_KERNEL);
@@ -1134,6 +1136,7 @@ void devl_port_unregister(struct devlink_port *devlink_port)
devlink_port_type_warn_cancel(devlink_port);
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
xa_erase(&devlink_port->devlink->ports, devlink_port->index);
+ xa_destroy(&devlink_port->params);
WARN_ON(!list_empty(&devlink_port->reporter_list));
devlink_port->registered = false;
}
--
2.48.1