Commit b1351527 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'devlink-expose-instance-locking-and-simplify-port-splitting'

Jakub Kicinski says:

====================
devlink: expose instance locking and simplify port splitting

This series puts the devlink ports fully under the devlink instance
lock's protection. As discussed in the past it implements my preferred
solution of exposing the instance lock to the drivers. This way drivers
which want to support port splitting can lock the devlink instance
themselves on the probe path, and we can take that lock in the core
on the split/unsplit paths.

nfp and mlxsw are converted, with slightly deeper changes done in
nfp since I'm more familiar with that driver.

Now that the devlink port is protected we can pass a pointer to
the drivers, instead of passing a port index and forcing the drivers
to do their own lookups. Both nfp and mlxsw can container_of() to
their own structures.
====================

Link: https://lore.kernel.org/r/20220315060009.1028519-1-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 49045b9c 706217c1
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -4,6 +4,22 @@ Linux Devlink Documentation
devlink is an API to expose device information and resources not directly
related to any device class, such as chip-wide/switch-ASIC-wide configuration.

Locking
-------

Driver facing APIs are currently transitioning to allow more explicit
locking. Drivers can use the existing ``devlink_*`` set of APIs, or
new APIs prefixed by ``devl_*``. The older APIs handle all the locking
in devlink core, but don't allow registration of most sub-objects once
the main devlink object is itself registered. The newer ``devl_*`` APIs assume
the devlink instance lock is already held. Drivers can take the instance
lock by calling ``devl_lock()``. It is also held in most of the callbacks.
Eventually all callbacks will be invoked under the devlink instance lock,
refer to the use of the ``DEVLINK_NL_FLAG_NO_LOCK`` flag in devlink core
to find out which callbacks are not converted, yet.

Drivers are encouraged to use the devlink instance lock for their own needs.

Interface documentation
-----------------------

+16 −20
Original line number Diff line number Diff line
@@ -1217,36 +1217,37 @@ static void mlxsw_core_fw_params_unregister(struct mlxsw_core *mlxsw_core)
				  ARRAY_SIZE(mlxsw_core_fw_devlink_params));
}

static void *__dl_port(struct devlink_port *devlink_port)
{
	return container_of(devlink_port, struct mlxsw_core_port, devlink_port);
}

static int mlxsw_devlink_port_split(struct devlink *devlink,
				    unsigned int port_index,
				    struct devlink_port *port,
				    unsigned int count,
				    struct netlink_ext_ack *extack)
{
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(port);
	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);

	if (port_index >= mlxsw_core->max_ports) {
		NL_SET_ERR_MSG_MOD(extack, "Port index exceeds maximum number of ports");
		return -EINVAL;
	}
	if (!mlxsw_core->driver->port_split)
		return -EOPNOTSUPP;
	return mlxsw_core->driver->port_split(mlxsw_core, port_index, count,
					      extack);
	return mlxsw_core->driver->port_split(mlxsw_core,
					      mlxsw_core_port->local_port,
					      count, extack);
}

static int mlxsw_devlink_port_unsplit(struct devlink *devlink,
				      unsigned int port_index,
				      struct devlink_port *port,
				      struct netlink_ext_ack *extack)
{
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(port);
	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);

	if (port_index >= mlxsw_core->max_ports) {
		NL_SET_ERR_MSG_MOD(extack, "Port index exceeds maximum number of ports");
		return -EINVAL;
	}
	if (!mlxsw_core->driver->port_unsplit)
		return -EOPNOTSUPP;
	return mlxsw_core->driver->port_unsplit(mlxsw_core, port_index,
	return mlxsw_core->driver->port_unsplit(mlxsw_core,
						mlxsw_core_port->local_port,
						extack);
}

@@ -1280,11 +1281,6 @@ mlxsw_devlink_sb_pool_set(struct devlink *devlink,
					 extack);
}

static void *__dl_port(struct devlink_port *devlink_port)
{
	return container_of(devlink_port, struct mlxsw_core_port, devlink_port);
}

static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port,
				       enum devlink_port_type port_type)
{
@@ -2983,7 +2979,7 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
	attrs.switch_id.id_len = switch_id_len;
	mlxsw_core_port->local_port = local_port;
	devlink_port_attrs_set(devlink_port, &attrs);
	err = devlink_port_register(devlink, devlink_port, local_port);
	err = devl_port_register(devlink, devlink_port, local_port);
	if (err)
		memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
	return err;
@@ -2995,7 +2991,7 @@ static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u16 local_port
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	devlink_port_unregister(devlink_port);
	devl_port_unregister(devlink_port);
	memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
}

+6 −0
Original line number Diff line number Diff line
@@ -422,6 +422,7 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
			struct netlink_ext_ack *extack)
{
	struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core);
	struct devlink *devlink = priv_to_devlink(mlxsw_core);
	int err;

	mlxsw_m->core = mlxsw_core;
@@ -437,7 +438,9 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
		return err;
	}

	devl_lock(devlink);
	err = mlxsw_m_ports_create(mlxsw_m);
	devl_unlock(devlink);
	if (err) {
		dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n");
		return err;
@@ -449,8 +452,11 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core)
{
	struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core);
	struct devlink *devlink = priv_to_devlink(mlxsw_core);

	devl_lock(devlink);
	mlxsw_m_ports_remove(mlxsw_m);
	devl_unlock(devlink);
}

static const struct mlxsw_config_profile mlxsw_m_config_profile;
+7 −0
Original line number Diff line number Diff line
@@ -2818,6 +2818,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
			 struct netlink_ext_ack *extack)
{
	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
	struct devlink *devlink = priv_to_devlink(mlxsw_core);
	int err;

	mlxsw_sp->core = mlxsw_core;
@@ -2978,7 +2979,9 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
		goto err_sample_trigger_init;
	}

	devl_lock(devlink);
	err = mlxsw_sp_ports_create(mlxsw_sp);
	devl_unlock(devlink);
	if (err) {
		dev_err(mlxsw_sp->bus_info->dev, "Failed to create ports\n");
		goto err_ports_create;
@@ -3159,8 +3162,12 @@ static int mlxsw_sp4_init(struct mlxsw_core *mlxsw_core,
static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
{
	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
	struct devlink *devlink = priv_to_devlink(mlxsw_core);

	devl_lock(devlink);
	mlxsw_sp_ports_remove(mlxsw_sp);
	devl_unlock(devlink);

	rhashtable_destroy(&mlxsw_sp->sample_trigger_ht);
	mlxsw_sp_port_module_info_fini(mlxsw_sp);
	mlxsw_sp_dpipe_fini(mlxsw_sp);
+2 −2
Original line number Diff line number Diff line
@@ -266,7 +266,7 @@ nfp_flower_reprs_reify(struct nfp_app *app, enum nfp_repr_type type,
	int i, err, count = 0;

	reprs = rcu_dereference_protected(app->reprs[type],
					  lockdep_is_held(&app->pf->lock));
					  nfp_app_is_locked(app));
	if (!reprs)
		return 0;

@@ -295,7 +295,7 @@ nfp_flower_wait_repr_reify(struct nfp_app *app, atomic_t *replies, int tot_repl)
	if (!tot_repl)
		return 0;

	lockdep_assert_held(&app->pf->lock);
	assert_nfp_app_locked(app);
	if (!wait_event_timeout(priv->reify_wait_queue,
				atomic_read(replies) >= tot_repl,
				NFP_FL_REPLY_TIMEOUT)) {
Loading