drivers/net/ethernet/mellanox/mlx5/core/sriov.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/sriov.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/sriov.c
Extension
.c
Size
10833 bytes
Lines
380
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (err) {
			mlx5_core_warn(dev, "failed to enable VF %d (%d)\n", vf, err);
			continue;
		}

		err = mlx5_set_msix_vec_count(dev, vf + 1, num_msix_count);
		if (err) {
			mlx5_core_warn(dev,
				       "failed to set MSI-X vector counts VF %d, err %d\n",
				       vf, err);
			continue;
		}

		sriov->vfs_ctx[vf].enabled = 1;
		if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) {
			vport_num = mlx5_core_ec_sriov_enabled(dev) ?
					mlx5_core_ec_vf_vport_base(dev) + vf
					: vf + 1;
			err = sriov_restore_guids(dev, vf, vport_num);
			if (err) {
				mlx5_core_warn(dev,
					       "failed to restore VF %d settings, err %d\n",
					       vf, err);
				continue;
			}
		}
		mlx5_core_dbg(dev, "successfully enabled VF* %d\n", vf);
	}

	return 0;
}

static void
mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf, bool num_vf_change)
{
	struct mlx5_core_sriov *sriov = &dev->priv.sriov;
	bool wait_for_ec_vf_pages = true;
	bool wait_for_vf_pages = true;
	int err;
	int vf;

	for (vf = num_vfs - 1; vf >= 0; vf--) {
		if (!sriov->vfs_ctx[vf].enabled)
			continue;
		/* Notify the VF before its disablement to let it clean
		 * some resources.
		 */
		blocking_notifier_call_chain(&sriov->vfs_ctx[vf].notifier,
					     MLX5_PF_NOTIFY_DISABLE_VF, dev);
		err = mlx5_core_disable_hca(dev, vf + 1);
		if (err) {
			mlx5_core_warn(dev, "failed to disable VF %d\n", vf);
			continue;
		}
		sriov->vfs_ctx[vf].enabled = 0;
	}

	mlx5_eswitch_disable_sriov(dev->priv.eswitch, clear_vf);

	/* There are a number of scenarios when SRIOV is being disabled:
	 *     1. VFs or ECVFs had been created, and now set back to 0 (num_vf_change == true).
	 *		- If EC SRIOV is enabled then this flow is happening on the
	 *		  embedded platform, wait for only EC VF pages.
	 *		- If EC SRIOV is not enabled this flow is happening on non-embedded
	 *		  platform, wait for the VF pages.
	 *
	 *     2. The driver is being unloaded. In this case wait for all pages.
	 */
	if (num_vf_change) {
		if (mlx5_core_ec_sriov_enabled(dev))
			wait_for_vf_pages = false;
		else
			wait_for_ec_vf_pages = false;
	}

	if (wait_for_ec_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_EC_VF]))
		mlx5_core_warn(dev, "timeout reclaiming EC VFs pages\n");

	/* For ECPFs, skip waiting for host VF pages until ECPF is destroyed */
	if (mlx5_core_is_ecpf(dev))
		return;

	if (wait_for_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF]))
		mlx5_core_warn(dev, "timeout reclaiming VFs pages\n");
}

static int mlx5_sriov_enable(struct pci_dev *pdev, int num_vfs)
{
	struct mlx5_core_dev *dev  = pci_get_drvdata(pdev);
	struct devlink *devlink = priv_to_devlink(dev);

Annotation

Implementation Notes