drivers/vfio/pci/mlx5/cmd.c

Source file repositories/reference/linux-study-clean/drivers/vfio/pci/mlx5/cmd.c

File Facts

System
Linux kernel
Corpus path
drivers/vfio/pci/mlx5/cmd.c
Extension
.c
Size
50108 bytes
Lines
1810
Domain
Driver Families
Bucket
drivers/vfio
Inferred role
Driver Families: implementation source
Status
source 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 (!(query_flags & MLX5VF_QUERY_FINAL)) {
				*state_size = 0;
				complete(&mvdev->saving_migf->save_comp);
				return 0;
			}
			query_flags &= ~MLX5VF_QUERY_INC;
		}
		/* Block incremental query which is state-dependent */
		if (mvdev->saving_migf->state == MLX5_MIGF_STATE_ERROR) {
			complete(&mvdev->saving_migf->save_comp);
			return -ENODEV;
		}
	}

	MLX5_SET(query_vhca_migration_state_in, in, opcode,
		 MLX5_CMD_OP_QUERY_VHCA_MIGRATION_STATE);
	MLX5_SET(query_vhca_migration_state_in, in, vhca_id, mvdev->vhca_id);
	MLX5_SET(query_vhca_migration_state_in, in, op_mod, 0);
	MLX5_SET(query_vhca_migration_state_in, in, incremental,
		 query_flags & MLX5VF_QUERY_INC);
	MLX5_SET(query_vhca_migration_state_in, in, chunk, mvdev->chunk_mode);

	ret = mlx5_cmd_exec_inout(mvdev->mdev, query_vhca_migration_state, in,
				  out);
	if (inc)
		complete(&mvdev->saving_migf->save_comp);

	if (ret)
		return ret;

	*state_size = MLX5_GET(query_vhca_migration_state_out, out,
			       required_umem_size);
	if (total_size)
		*total_size = mvdev->chunk_mode ?
			MLX5_GET64(query_vhca_migration_state_out, out,
				   remaining_total_size) : *state_size;

	if (mig_state && mvdev->mig_state_cap)
		*mig_state = MLX5_GET(query_vhca_migration_state_out, out,
				      migration_state);

	return 0;
}

static void set_tracker_change_event(struct mlx5vf_pci_core_device *mvdev)
{
	mvdev->tracker.object_changed = true;
	complete(&mvdev->tracker_comp);
}

static void set_tracker_error(struct mlx5vf_pci_core_device *mvdev)
{
	/* Mark the tracker under an error and wake it up if it's running */
	mvdev->tracker.is_err = true;
	complete(&mvdev->tracker_comp);
}

static int mlx5fv_vf_event(struct notifier_block *nb,
			   unsigned long event, void *data)
{
	struct mlx5vf_pci_core_device *mvdev =
		container_of(nb, struct mlx5vf_pci_core_device, nb);

	switch (event) {
	case MLX5_PF_NOTIFY_ENABLE_VF:
		mutex_lock(&mvdev->state_mutex);
		mvdev->mdev_detach = false;
		mlx5vf_state_mutex_unlock(mvdev);
		break;
	case MLX5_PF_NOTIFY_DISABLE_VF:
		mlx5vf_cmd_close_migratable(mvdev);
		mutex_lock(&mvdev->state_mutex);
		mvdev->mdev_detach = true;
		mlx5vf_state_mutex_unlock(mvdev);
		break;
	default:
		break;
	}

	return 0;
}

void mlx5vf_cmd_close_migratable(struct mlx5vf_pci_core_device *mvdev)
{
	if (!mvdev->migrate_cap)
		return;

	/* Must be done outside the lock to let it progress */
	set_tracker_error(mvdev);
	mutex_lock(&mvdev->state_mutex);

Annotation

Implementation Notes