Commit 84a433a4 authored by Moshe Shemesh's avatar Moshe Shemesh Committed by Jakub Kicinski
Browse files

net/mlx5: Lock mlx5 devlink reload callbacks



Change devlink instance locks in mlx5 driver to have devlink reload
callbacks locked, while keeping all driver paths which lead to devl_ API
functions called by the driver locked.

Add mlx5_load_one_devl_locked() and mlx5_unload_one_devl_locked() which
are used by the paths which are already locked such as devlink reload
callbacks.

This patch makes the driver use devl_ API also for traps register as
these functions are called from the driver paths parallel to reload that
requires locking now.

Signed-off-by: default avatarMoshe Shemesh <moshe@nvidia.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c12f4c6a
Loading
Loading
Loading
Loading
+4 −15
Original line number Diff line number Diff line
@@ -335,13 +335,12 @@ static void del_adev(struct auxiliary_device *adev)

int mlx5_attach_device(struct mlx5_core_dev *dev)
{
	struct devlink *devlink = priv_to_devlink(dev);
	struct mlx5_priv *priv = &dev->priv;
	struct auxiliary_device *adev;
	struct auxiliary_driver *adrv;
	int ret = 0, i;

	devl_lock(devlink);
	devl_assert_locked(priv_to_devlink(dev));
	mutex_lock(&mlx5_intf_mutex);
	priv->flags &= ~MLX5_PRIV_FLAGS_DETACH;
	priv->flags |= MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
@@ -394,20 +393,18 @@ int mlx5_attach_device(struct mlx5_core_dev *dev)
	}
	priv->flags &= ~MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
	mutex_unlock(&mlx5_intf_mutex);
	devl_unlock(devlink);
	return ret;
}

void mlx5_detach_device(struct mlx5_core_dev *dev)
{
	struct devlink *devlink = priv_to_devlink(dev);
	struct mlx5_priv *priv = &dev->priv;
	struct auxiliary_device *adev;
	struct auxiliary_driver *adrv;
	pm_message_t pm = {};
	int i;

	devl_lock(devlink);
	devl_assert_locked(priv_to_devlink(dev));
	mutex_lock(&mlx5_intf_mutex);
	priv->flags |= MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
	for (i = ARRAY_SIZE(mlx5_adev_devices) - 1; i >= 0; i--) {
@@ -441,21 +438,17 @@ void mlx5_detach_device(struct mlx5_core_dev *dev)
	priv->flags &= ~MLX5_PRIV_FLAGS_MLX5E_LOCKED_FLOW;
	priv->flags |= MLX5_PRIV_FLAGS_DETACH;
	mutex_unlock(&mlx5_intf_mutex);
	devl_unlock(devlink);
}

int mlx5_register_device(struct mlx5_core_dev *dev)
{
	struct devlink *devlink;
	int ret;

	devlink = priv_to_devlink(dev);
	devl_lock(devlink);
	devl_assert_locked(priv_to_devlink(dev));
	mutex_lock(&mlx5_intf_mutex);
	dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV;
	ret = mlx5_rescan_drivers_locked(dev);
	mutex_unlock(&mlx5_intf_mutex);
	devl_unlock(devlink);
	if (ret)
		mlx5_unregister_device(dev);

@@ -464,15 +457,11 @@ int mlx5_register_device(struct mlx5_core_dev *dev)

void mlx5_unregister_device(struct mlx5_core_dev *dev)
{
	struct devlink *devlink;

	devlink = priv_to_devlink(dev);
	devl_lock(devlink);
	devl_assert_locked(priv_to_devlink(dev));
	mutex_lock(&mlx5_intf_mutex);
	dev->priv.flags = MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV;
	mlx5_rescan_drivers_locked(dev);
	mutex_unlock(&mlx5_intf_mutex);
	devl_unlock(devlink);
}

static int add_drivers(struct mlx5_core_dev *dev)
+31 −19
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli
	if (err)
		return err;

	mlx5_unload_one(dev);
	mlx5_unload_one_devl_locked(dev);
	err = mlx5_health_wait_pci_up(dev);
	if (err)
		NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset");
@@ -143,6 +143,7 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
	struct mlx5_core_dev *dev = devlink_priv(devlink);
	struct pci_dev *pdev = dev->pdev;
	bool sf_dev_allocated;
	int ret = 0;

	sf_dev_allocated = mlx5_sf_dev_allocated(dev);
	if (sf_dev_allocated) {
@@ -163,19 +164,25 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
		NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable");
	}

	devl_lock(devlink);
	switch (action) {
	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
		mlx5_unload_one(dev);
		return 0;
		mlx5_unload_one_devl_locked(dev);
		break;
	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
			return mlx5_devlink_trigger_fw_live_patch(devlink, extack);
		return mlx5_devlink_reload_fw_activate(devlink, extack);
			ret = mlx5_devlink_trigger_fw_live_patch(devlink, extack);
		else
			ret = mlx5_devlink_reload_fw_activate(devlink, extack);
		break;
	default:
		/* Unsupported action should not get to this function */
		WARN_ON(1);
		return -EOPNOTSUPP;
		ret = -EOPNOTSUPP;
	}

	devl_unlock(devlink);
	return ret;
}

static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action,
@@ -183,24 +190,29 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a
				  struct netlink_ext_ack *extack)
{
	struct mlx5_core_dev *dev = devlink_priv(devlink);
	int ret = 0;

	devl_lock(devlink);
	*actions_performed = BIT(action);
	switch (action) {
	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
		return mlx5_load_one(dev, false);
		ret = mlx5_load_one_devl_locked(dev, false);
		break;
	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
			break;
		/* On fw_activate action, also driver is reloaded and reinit performed */
		*actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
		return mlx5_load_one(dev, false);
		ret = mlx5_load_one_devl_locked(dev, false);
		break;
	default:
		/* Unsupported action should not get to this function */
		WARN_ON(1);
		return -EOPNOTSUPP;
		ret = -EOPNOTSUPP;
	}

	return 0;
	devl_unlock(devlink);
	return ret;
}

static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id)
@@ -837,27 +849,27 @@ static int mlx5_devlink_traps_register(struct devlink *devlink)
	struct mlx5_core_dev *core_dev = devlink_priv(devlink);
	int err;

	err = devlink_trap_groups_register(devlink, mlx5_trap_groups_arr,
	err = devl_trap_groups_register(devlink, mlx5_trap_groups_arr,
					ARRAY_SIZE(mlx5_trap_groups_arr));
	if (err)
		return err;

	err = devlink_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr),
	err = devl_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr),
				  &core_dev->priv);
	if (err)
		goto err_trap_group;
	return 0;

err_trap_group:
	devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
	devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
				    ARRAY_SIZE(mlx5_trap_groups_arr));
	return err;
}

static void mlx5_devlink_traps_unregister(struct devlink *devlink)
{
	devlink_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr));
	devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
	devl_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr));
	devl_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
				    ARRAY_SIZE(mlx5_trap_groups_arr));
}

+4 −14
Original line number Diff line number Diff line
@@ -1300,20 +1300,19 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
 */
int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
{
	struct devlink *devlink;
	bool toggle_lag;
	int ret;

	if (!mlx5_esw_allowed(esw))
		return 0;

	devl_assert_locked(priv_to_devlink(esw->dev));

	toggle_lag = !mlx5_esw_is_fdb_created(esw);

	if (toggle_lag)
		mlx5_lag_disable_change(esw->dev);

	devlink = priv_to_devlink(esw->dev);
	devl_lock(devlink);
	down_write(&esw->mode_lock);
	if (!mlx5_esw_is_fdb_created(esw)) {
		ret = mlx5_eswitch_enable_locked(esw, num_vfs);
@@ -1327,7 +1326,6 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
			esw->esw_funcs.num_vfs = num_vfs;
	}
	up_write(&esw->mode_lock);
	devl_unlock(devlink);

	if (toggle_lag)
		mlx5_lag_enable_change(esw->dev);
@@ -1338,13 +1336,10 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
/* When disabling sriov, free driver level resources. */
void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
{
	struct devlink *devlink;

	if (!mlx5_esw_allowed(esw))
		return;

	devlink = priv_to_devlink(esw->dev);
	devl_lock(devlink);
	devl_assert_locked(priv_to_devlink(esw->dev));
	down_write(&esw->mode_lock);
	/* If driver is unloaded, this function is called twice by remove_one()
	 * and mlx5_unload(). Prevent the second call.
@@ -1373,7 +1368,6 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)

unlock:
	up_write(&esw->mode_lock);
	devl_unlock(devlink);
}

/* Free resources for corresponding eswitch mode. It is called by devlink
@@ -1407,18 +1401,14 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw)

void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
{
	struct devlink *devlink;

	if (!mlx5_esw_allowed(esw))
		return;

	devl_assert_locked(priv_to_devlink(esw->dev));
	mlx5_lag_disable_change(esw->dev);
	devlink = priv_to_devlink(esw->dev);
	devl_lock(devlink);
	down_write(&esw->mode_lock);
	mlx5_eswitch_disable_locked(esw);
	up_write(&esw->mode_lock);
	devl_unlock(devlink);
	mlx5_lag_enable_change(esw->dev);
}

+32 −2
Original line number Diff line number Diff line
@@ -1304,8 +1304,10 @@ static void mlx5_unload(struct mlx5_core_dev *dev)

int mlx5_init_one(struct mlx5_core_dev *dev)
{
	struct devlink *devlink = priv_to_devlink(dev);
	int err = 0;

	devl_lock(devlink);
	mutex_lock(&dev->intf_state_mutex);
	dev->state = MLX5_DEVICE_STATE_UP;

@@ -1334,6 +1336,7 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
		goto err_register;

	mutex_unlock(&dev->intf_state_mutex);
	devl_unlock(devlink);
	return 0;

err_register:
@@ -1348,11 +1351,15 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
err_function:
	dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
	mutex_unlock(&dev->intf_state_mutex);
	devl_unlock(devlink);
	return err;
}

void mlx5_uninit_one(struct mlx5_core_dev *dev)
{
	struct devlink *devlink = priv_to_devlink(dev);

	devl_lock(devlink);
	mutex_lock(&dev->intf_state_mutex);

	mlx5_unregister_device(dev);
@@ -1371,13 +1378,15 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
	mlx5_function_teardown(dev, true);
out:
	mutex_unlock(&dev->intf_state_mutex);
	devl_unlock(devlink);
}

int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery)
int mlx5_load_one_devl_locked(struct mlx5_core_dev *dev, bool recovery)
{
	int err = 0;
	u64 timeout;

	devl_assert_locked(priv_to_devlink(dev));
	mutex_lock(&dev->intf_state_mutex);
	if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
		mlx5_core_warn(dev, "interface is up, NOP\n");
@@ -1419,8 +1428,20 @@ int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery)
	return err;
}

void mlx5_unload_one(struct mlx5_core_dev *dev)
int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery)
{
	struct devlink *devlink = priv_to_devlink(dev);
	int ret;

	devl_lock(devlink);
	ret = mlx5_load_one_devl_locked(dev, recovery);
	devl_unlock(devlink);
	return ret;
}

void mlx5_unload_one_devl_locked(struct mlx5_core_dev *dev)
{
	devl_assert_locked(priv_to_devlink(dev));
	mutex_lock(&dev->intf_state_mutex);

	mlx5_detach_device(dev);
@@ -1438,6 +1459,15 @@ void mlx5_unload_one(struct mlx5_core_dev *dev)
	mutex_unlock(&dev->intf_state_mutex);
}

void mlx5_unload_one(struct mlx5_core_dev *dev)
{
	struct devlink *devlink = priv_to_devlink(dev);

	devl_lock(devlink);
	mlx5_unload_one_devl_locked(dev);
	devl_unlock(devlink);
}

static const int types[] = {
	MLX5_CAP_GENERAL,
	MLX5_CAP_GENERAL_2,
+2 −0
Original line number Diff line number Diff line
@@ -290,7 +290,9 @@ void mlx5_mdev_uninit(struct mlx5_core_dev *dev);
int mlx5_init_one(struct mlx5_core_dev *dev);
void mlx5_uninit_one(struct mlx5_core_dev *dev);
void mlx5_unload_one(struct mlx5_core_dev *dev);
void mlx5_unload_one_devl_locked(struct mlx5_core_dev *dev);
int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery);
int mlx5_load_one_devl_locked(struct mlx5_core_dev *dev, bool recovery);

int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out);

Loading