Commit 13719a5b authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'take-devlink-lock-on-mlx4-and-mlx5-callbacks'

Moshe Shemesh says:

====================
Take devlink lock on mlx4 and mlx5 callbacks

Prepare mlx4 and mlx5 drivers to have all devlink callbacks called with
devlink instance locked. Change mlx4 driver to use devl_ API where
needed to have devlink reload callbacks locked. Change mlx5 driver to
use devl_ API where needed to have devlink reload and devlink health
callbacks locked.

As mlx5 is the only driver which needed changes to enable calling health
callbacks with devlink instance locked, this patchset also removes
DEVLINK_NL_FLAG_NO_LOCK flag from devlink health callbacks.

This patchset will be followed by a patchset that will remove
DEVLINK_NL_FLAG_NO_LOCK flag from devlink and will remove devlink_mutex.
====================

Link: https://lore.kernel.org/r/1659023630-32006-1-git-send-email-moshe@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 1515a1b8 c90005b5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -204,9 +204,13 @@ void mlx4_enter_error_state(struct mlx4_dev_persistent *persist)

static void mlx4_handle_error_state(struct mlx4_dev_persistent *persist)
{
	struct mlx4_dev *dev = persist->dev;
	struct devlink *devlink;
	int err = 0;

	mlx4_enter_error_state(persist);
	devlink = priv_to_devlink(mlx4_priv(dev));
	devl_lock(devlink);
	mutex_lock(&persist->interface_state_mutex);
	if (persist->interface_state & MLX4_INTERFACE_STATE_UP &&
	    !(persist->interface_state & MLX4_INTERFACE_STATE_DELETION)) {
@@ -215,6 +219,7 @@ static void mlx4_handle_error_state(struct mlx4_dev_persistent *persist)
			  err);
	}
	mutex_unlock(&persist->interface_state_mutex);
	devl_unlock(devlink);
}

static void dump_err_buf(struct mlx4_dev *dev)
+10 −10
Original line number Diff line number Diff line
@@ -226,7 +226,7 @@ int mlx4_crdump_init(struct mlx4_dev *dev)

	/* Create cr-space region */
	crdump->region_crspace =
		devlink_region_create(devlink,
		devl_region_create(devlink,
				   &region_cr_space_ops,
				   MAX_NUM_OF_DUMPS_TO_STORE,
				   pci_resource_len(pdev, 0));
@@ -237,7 +237,7 @@ int mlx4_crdump_init(struct mlx4_dev *dev)

	/* Create fw-health region */
	crdump->region_fw_health =
		devlink_region_create(devlink,
		devl_region_create(devlink,
				   &region_fw_health_ops,
				   MAX_NUM_OF_DUMPS_TO_STORE,
				   HEALTH_BUFFER_SIZE);
@@ -253,6 +253,6 @@ void mlx4_crdump_end(struct mlx4_dev *dev)
{
	struct mlx4_fw_crdump *crdump = &dev->persist->crdump;

	devlink_region_destroy(crdump->region_fw_health);
	devlink_region_destroy(crdump->region_crspace);
	devl_region_destroy(crdump->region_fw_health);
	devl_region_destroy(crdump->region_crspace);
}
+39 −5
Original line number Diff line number Diff line
@@ -3033,7 +3033,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
	struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
	int err;

	err = devlink_port_register(devlink, &info->devlink_port, port);
	err = devl_port_register(devlink, &info->devlink_port, port);
	if (err)
		return err;

@@ -3071,7 +3071,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
	err = device_create_file(&dev->persist->pdev->dev, &info->port_attr);
	if (err) {
		mlx4_err(dev, "Failed to create file for port %d\n", port);
		devlink_port_unregister(&info->devlink_port);
		devl_port_unregister(&info->devlink_port);
		info->port = -1;
		return err;
	}
@@ -3093,7 +3093,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
		mlx4_err(dev, "Failed to create mtu file for port %d\n", port);
		device_remove_file(&info->dev->persist->pdev->dev,
				   &info->port_attr);
		devlink_port_unregister(&info->devlink_port);
		devl_port_unregister(&info->devlink_port);
		info->port = -1;
		return err;
	}
@@ -3109,7 +3109,7 @@ static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
	device_remove_file(&info->dev->persist->pdev->dev, &info->port_attr);
	device_remove_file(&info->dev->persist->pdev->dev,
			   &info->port_mtu_attr);
	devlink_port_unregister(&info->devlink_port);
	devl_port_unregister(&info->devlink_port);

#ifdef CONFIG_RFS_ACCEL
	free_irq_cpu_rmap(info->rmap);
@@ -3333,6 +3333,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,
			 int total_vfs, int *nvfs, struct mlx4_priv *priv,
			 int reset_flow)
{
	struct devlink *devlink = priv_to_devlink(priv);
	struct mlx4_dev *dev;
	unsigned sum = 0;
	int err;
@@ -3341,6 +3342,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,
	struct mlx4_dev_cap *dev_cap = NULL;
	int existing_vfs = 0;

	devl_assert_locked(devlink);
	dev = &priv->dev;

	INIT_LIST_HEAD(&priv->ctx_list);
@@ -3956,9 +3958,11 @@ static int mlx4_devlink_reload_down(struct devlink *devlink, bool netns_change,
		NL_SET_ERR_MSG_MOD(extack, "Namespace change is not supported");
		return -EOPNOTSUPP;
	}
	devl_lock(devlink);
	if (persist->num_vfs)
		mlx4_warn(persist->dev, "Reload performed on PF, will cause reset on operating Virtual Functions\n");
	mlx4_restart_one_down(persist->pdev);
	devl_unlock(devlink);
	return 0;
}

@@ -3971,8 +3975,10 @@ static int mlx4_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a
	struct mlx4_dev_persistent *persist = dev->persist;
	int err;

	devl_lock(devlink);
	*actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
	err = mlx4_restart_one_up(persist->pdev, true, devlink);
	devl_unlock(devlink);
	if (err)
		mlx4_err(persist->dev, "mlx4_restart_one_up failed, ret=%d\n",
			 err);
@@ -3999,6 +4005,7 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
	devlink = devlink_alloc(&mlx4_devlink_ops, sizeof(*priv), &pdev->dev);
	if (!devlink)
		return -ENOMEM;
	devl_lock(devlink);
	priv = devlink_priv(devlink);

	dev       = &priv->dev;
@@ -4026,6 +4033,7 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)

	pci_save_state(pdev);
	devlink_set_features(devlink, DEVLINK_F_RELOAD);
	devl_unlock(devlink);
	devlink_register(devlink);
	return 0;

@@ -4035,6 +4043,7 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
err_devlink_unregister:
	kfree(dev->persist);
err_devlink_free:
	devl_unlock(devlink);
	devlink_free(devlink);
	return ret;
}
@@ -4056,8 +4065,11 @@ static void mlx4_unload_one(struct pci_dev *pdev)
	struct mlx4_dev  *dev  = persist->dev;
	struct mlx4_priv *priv = mlx4_priv(dev);
	int               pci_dev_data;
	struct devlink *devlink;
	int p, i;

	devlink = priv_to_devlink(priv);
	devl_assert_locked(devlink);
	if (priv->removed)
		return;

@@ -4137,6 +4149,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)

	devlink_unregister(devlink);

	devl_lock(devlink);
	if (mlx4_is_slave(dev))
		persist->interface_state |= MLX4_INTERFACE_STATE_NOWAIT;

@@ -4172,6 +4185,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
	devlink_params_unregister(devlink, mlx4_devlink_params,
				  ARRAY_SIZE(mlx4_devlink_params));
	kfree(dev->persist);
	devl_unlock(devlink);
	devlink_free(devlink);
}

@@ -4292,15 +4306,20 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
					      pci_channel_state_t state)
{
	struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
	struct mlx4_dev *dev = persist->dev;
	struct devlink *devlink;

	mlx4_err(persist->dev, "mlx4_pci_err_detected was called\n");
	mlx4_enter_error_state(persist);

	devlink = priv_to_devlink(mlx4_priv(dev));
	devl_lock(devlink);
	mutex_lock(&persist->interface_state_mutex);
	if (persist->interface_state & MLX4_INTERFACE_STATE_UP)
		mlx4_unload_one(pdev);

	mutex_unlock(&persist->interface_state_mutex);
	devl_unlock(devlink);
	if (state == pci_channel_io_perm_failure)
		return PCI_ERS_RESULT_DISCONNECT;

@@ -4333,6 +4352,7 @@ static void mlx4_pci_resume(struct pci_dev *pdev)
	struct mlx4_dev	 *dev  = persist->dev;
	struct mlx4_priv *priv = mlx4_priv(dev);
	int nvfs[MLX4_MAX_PORTS + 1] = {0, 0, 0};
	struct devlink *devlink;
	int total_vfs;
	int err;

@@ -4340,6 +4360,8 @@ static void mlx4_pci_resume(struct pci_dev *pdev)
	total_vfs = dev->persist->num_vfs;
	memcpy(nvfs, dev->persist->nvfs, sizeof(dev->persist->nvfs));

	devlink = priv_to_devlink(priv);
	devl_lock(devlink);
	mutex_lock(&persist->interface_state_mutex);
	if (!(persist->interface_state & MLX4_INTERFACE_STATE_UP)) {
		err = mlx4_load_one(pdev, priv->pci_dev_data, total_vfs, nvfs,
@@ -4358,19 +4380,23 @@ static void mlx4_pci_resume(struct pci_dev *pdev)
	}
end:
	mutex_unlock(&persist->interface_state_mutex);

	devl_unlock(devlink);
}

static void mlx4_shutdown(struct pci_dev *pdev)
{
	struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
	struct mlx4_dev *dev = persist->dev;
	struct devlink *devlink;

	mlx4_info(persist->dev, "mlx4_shutdown was called\n");
	devlink = priv_to_devlink(mlx4_priv(dev));
	devl_lock(devlink);
	mutex_lock(&persist->interface_state_mutex);
	if (persist->interface_state & MLX4_INTERFACE_STATE_UP)
		mlx4_unload_one(pdev);
	mutex_unlock(&persist->interface_state_mutex);
	devl_unlock(devlink);
	mlx4_pci_disable_device(dev);
}

@@ -4385,12 +4411,16 @@ static int __maybe_unused mlx4_suspend(struct device *dev_d)
	struct pci_dev *pdev = to_pci_dev(dev_d);
	struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
	struct mlx4_dev	*dev = persist->dev;
	struct devlink *devlink;

	mlx4_err(dev, "suspend was called\n");
	devlink = priv_to_devlink(mlx4_priv(dev));
	devl_lock(devlink);
	mutex_lock(&persist->interface_state_mutex);
	if (persist->interface_state & MLX4_INTERFACE_STATE_UP)
		mlx4_unload_one(pdev);
	mutex_unlock(&persist->interface_state_mutex);
	devl_unlock(devlink);

	return 0;
}
@@ -4402,6 +4432,7 @@ static int __maybe_unused mlx4_resume(struct device *dev_d)
	struct mlx4_dev	*dev = persist->dev;
	struct mlx4_priv *priv = mlx4_priv(dev);
	int nvfs[MLX4_MAX_PORTS + 1] = {0, 0, 0};
	struct devlink *devlink;
	int total_vfs;
	int ret = 0;

@@ -4409,6 +4440,8 @@ static int __maybe_unused mlx4_resume(struct device *dev_d)
	total_vfs = dev->persist->num_vfs;
	memcpy(nvfs, dev->persist->nvfs, sizeof(dev->persist->nvfs));

	devlink = priv_to_devlink(priv);
	devl_lock(devlink);
	mutex_lock(&persist->interface_state_mutex);
	if (!(persist->interface_state & MLX4_INTERFACE_STATE_UP)) {
		ret = mlx4_load_one(pdev, priv->pci_dev_data, total_vfs,
@@ -4422,6 +4455,7 @@ static int __maybe_unused mlx4_resume(struct device *dev_d)
		}
	}
	mutex_unlock(&persist->interface_state_mutex);
	devl_unlock(devlink);

	return ret;
}
+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)
+40 −19
Original line number Diff line number Diff line
@@ -104,7 +104,16 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli
	if (err)
		return err;

	return mlx5_fw_reset_wait_reset_done(dev);
	err = mlx5_fw_reset_wait_reset_done(dev);
	if (err)
		return err;

	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");

	return err;
}

static int mlx5_devlink_trigger_fw_live_patch(struct devlink *devlink,
@@ -134,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) {
@@ -154,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,
@@ -174,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)
@@ -828,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));
}

Loading