162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#ifndef MLX5_VFIO_CMD_H 762306a36Sopenharmony_ci#define MLX5_VFIO_CMD_H 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/vfio_pci_core.h> 1162306a36Sopenharmony_ci#include <linux/mlx5/driver.h> 1262306a36Sopenharmony_ci#include <linux/mlx5/vport.h> 1362306a36Sopenharmony_ci#include <linux/mlx5/cq.h> 1462306a36Sopenharmony_ci#include <linux/mlx5/qp.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define MLX5VF_PRE_COPY_SUPP(mvdev) \ 1762306a36Sopenharmony_ci ((mvdev)->core_device.vdev.migration_flags & VFIO_MIGRATION_PRE_COPY) 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cienum mlx5_vf_migf_state { 2062306a36Sopenharmony_ci MLX5_MIGF_STATE_ERROR = 1, 2162306a36Sopenharmony_ci MLX5_MIGF_STATE_PRE_COPY_ERROR, 2262306a36Sopenharmony_ci MLX5_MIGF_STATE_PRE_COPY, 2362306a36Sopenharmony_ci MLX5_MIGF_STATE_SAVE_LAST, 2462306a36Sopenharmony_ci MLX5_MIGF_STATE_COMPLETE, 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cienum mlx5_vf_load_state { 2862306a36Sopenharmony_ci MLX5_VF_LOAD_STATE_READ_IMAGE_NO_HEADER, 2962306a36Sopenharmony_ci MLX5_VF_LOAD_STATE_READ_HEADER, 3062306a36Sopenharmony_ci MLX5_VF_LOAD_STATE_PREP_HEADER_DATA, 3162306a36Sopenharmony_ci MLX5_VF_LOAD_STATE_READ_HEADER_DATA, 3262306a36Sopenharmony_ci MLX5_VF_LOAD_STATE_PREP_IMAGE, 3362306a36Sopenharmony_ci MLX5_VF_LOAD_STATE_READ_IMAGE, 3462306a36Sopenharmony_ci MLX5_VF_LOAD_STATE_LOAD_IMAGE, 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistruct mlx5_vf_migration_tag_stop_copy_data { 3862306a36Sopenharmony_ci __le64 stop_copy_size; 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cienum mlx5_vf_migf_header_flags { 4262306a36Sopenharmony_ci MLX5_MIGF_HEADER_FLAGS_TAG_MANDATORY = 0, 4362306a36Sopenharmony_ci MLX5_MIGF_HEADER_FLAGS_TAG_OPTIONAL = 1 << 0, 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cienum mlx5_vf_migf_header_tag { 4762306a36Sopenharmony_ci MLX5_MIGF_HEADER_TAG_FW_DATA = 0, 4862306a36Sopenharmony_ci MLX5_MIGF_HEADER_TAG_STOP_COPY_SIZE = 1 << 0, 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistruct mlx5_vf_migration_header { 5262306a36Sopenharmony_ci __le64 record_size; 5362306a36Sopenharmony_ci /* For future use in case we may need to change the kernel protocol */ 5462306a36Sopenharmony_ci __le32 flags; /* Use mlx5_vf_migf_header_flags */ 5562306a36Sopenharmony_ci __le32 tag; /* Use mlx5_vf_migf_header_tag */ 5662306a36Sopenharmony_ci __u8 data[]; /* Its size is given in the record_size */ 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct mlx5_vhca_data_buffer { 6062306a36Sopenharmony_ci struct sg_append_table table; 6162306a36Sopenharmony_ci loff_t start_pos; 6262306a36Sopenharmony_ci u64 length; 6362306a36Sopenharmony_ci u64 allocated_length; 6462306a36Sopenharmony_ci u32 mkey; 6562306a36Sopenharmony_ci enum dma_data_direction dma_dir; 6662306a36Sopenharmony_ci u8 dmaed:1; 6762306a36Sopenharmony_ci struct list_head buf_elm; 6862306a36Sopenharmony_ci struct mlx5_vf_migration_file *migf; 6962306a36Sopenharmony_ci /* Optimize mlx5vf_get_migration_page() for sequential access */ 7062306a36Sopenharmony_ci struct scatterlist *last_offset_sg; 7162306a36Sopenharmony_ci unsigned int sg_last_entry; 7262306a36Sopenharmony_ci unsigned long last_offset; 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistruct mlx5vf_async_data { 7662306a36Sopenharmony_ci struct mlx5_async_work cb_work; 7762306a36Sopenharmony_ci struct work_struct work; 7862306a36Sopenharmony_ci struct mlx5_vhca_data_buffer *buf; 7962306a36Sopenharmony_ci struct mlx5_vhca_data_buffer *header_buf; 8062306a36Sopenharmony_ci int status; 8162306a36Sopenharmony_ci u8 last_chunk:1; 8262306a36Sopenharmony_ci void *out; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistruct mlx5_vf_migration_file { 8662306a36Sopenharmony_ci struct file *filp; 8762306a36Sopenharmony_ci struct mutex lock; 8862306a36Sopenharmony_ci enum mlx5_vf_migf_state state; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci enum mlx5_vf_load_state load_state; 9162306a36Sopenharmony_ci u32 pdn; 9262306a36Sopenharmony_ci loff_t max_pos; 9362306a36Sopenharmony_ci u64 record_size; 9462306a36Sopenharmony_ci u32 record_tag; 9562306a36Sopenharmony_ci u64 stop_copy_prep_size; 9662306a36Sopenharmony_ci u64 pre_copy_initial_bytes; 9762306a36Sopenharmony_ci struct mlx5_vhca_data_buffer *buf; 9862306a36Sopenharmony_ci struct mlx5_vhca_data_buffer *buf_header; 9962306a36Sopenharmony_ci spinlock_t list_lock; 10062306a36Sopenharmony_ci struct list_head buf_list; 10162306a36Sopenharmony_ci struct list_head avail_list; 10262306a36Sopenharmony_ci struct mlx5vf_pci_core_device *mvdev; 10362306a36Sopenharmony_ci wait_queue_head_t poll_wait; 10462306a36Sopenharmony_ci struct completion save_comp; 10562306a36Sopenharmony_ci struct mlx5_async_ctx async_ctx; 10662306a36Sopenharmony_ci struct mlx5vf_async_data async_data; 10762306a36Sopenharmony_ci}; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistruct mlx5_vhca_cq_buf { 11062306a36Sopenharmony_ci struct mlx5_frag_buf_ctrl fbc; 11162306a36Sopenharmony_ci struct mlx5_frag_buf frag_buf; 11262306a36Sopenharmony_ci int cqe_size; 11362306a36Sopenharmony_ci int nent; 11462306a36Sopenharmony_ci}; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistruct mlx5_vhca_cq { 11762306a36Sopenharmony_ci struct mlx5_vhca_cq_buf buf; 11862306a36Sopenharmony_ci struct mlx5_db db; 11962306a36Sopenharmony_ci struct mlx5_core_cq mcq; 12062306a36Sopenharmony_ci size_t ncqe; 12162306a36Sopenharmony_ci}; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistruct mlx5_vhca_recv_buf { 12462306a36Sopenharmony_ci u32 npages; 12562306a36Sopenharmony_ci struct page **page_list; 12662306a36Sopenharmony_ci dma_addr_t *dma_addrs; 12762306a36Sopenharmony_ci u32 next_rq_offset; 12862306a36Sopenharmony_ci u32 mkey; 12962306a36Sopenharmony_ci}; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistruct mlx5_vhca_qp { 13262306a36Sopenharmony_ci struct mlx5_frag_buf buf; 13362306a36Sopenharmony_ci struct mlx5_db db; 13462306a36Sopenharmony_ci struct mlx5_vhca_recv_buf recv_buf; 13562306a36Sopenharmony_ci u32 tracked_page_size; 13662306a36Sopenharmony_ci u32 max_msg_size; 13762306a36Sopenharmony_ci u32 qpn; 13862306a36Sopenharmony_ci struct { 13962306a36Sopenharmony_ci unsigned int pc; 14062306a36Sopenharmony_ci unsigned int cc; 14162306a36Sopenharmony_ci unsigned int wqe_cnt; 14262306a36Sopenharmony_ci __be32 *db; 14362306a36Sopenharmony_ci struct mlx5_frag_buf_ctrl fbc; 14462306a36Sopenharmony_ci } rq; 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistruct mlx5_vhca_page_tracker { 14862306a36Sopenharmony_ci u32 id; 14962306a36Sopenharmony_ci u32 pdn; 15062306a36Sopenharmony_ci u8 is_err:1; 15162306a36Sopenharmony_ci struct mlx5_uars_page *uar; 15262306a36Sopenharmony_ci struct mlx5_vhca_cq cq; 15362306a36Sopenharmony_ci struct mlx5_vhca_qp *host_qp; 15462306a36Sopenharmony_ci struct mlx5_vhca_qp *fw_qp; 15562306a36Sopenharmony_ci struct mlx5_nb nb; 15662306a36Sopenharmony_ci int status; 15762306a36Sopenharmony_ci}; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistruct mlx5vf_pci_core_device { 16062306a36Sopenharmony_ci struct vfio_pci_core_device core_device; 16162306a36Sopenharmony_ci int vf_id; 16262306a36Sopenharmony_ci u16 vhca_id; 16362306a36Sopenharmony_ci u8 migrate_cap:1; 16462306a36Sopenharmony_ci u8 deferred_reset:1; 16562306a36Sopenharmony_ci u8 mdev_detach:1; 16662306a36Sopenharmony_ci u8 log_active:1; 16762306a36Sopenharmony_ci struct completion tracker_comp; 16862306a36Sopenharmony_ci /* protect migration state */ 16962306a36Sopenharmony_ci struct mutex state_mutex; 17062306a36Sopenharmony_ci enum vfio_device_mig_state mig_state; 17162306a36Sopenharmony_ci /* protect the reset_done flow */ 17262306a36Sopenharmony_ci spinlock_t reset_lock; 17362306a36Sopenharmony_ci struct mlx5_vf_migration_file *resuming_migf; 17462306a36Sopenharmony_ci struct mlx5_vf_migration_file *saving_migf; 17562306a36Sopenharmony_ci struct mlx5_vhca_page_tracker tracker; 17662306a36Sopenharmony_ci struct workqueue_struct *cb_wq; 17762306a36Sopenharmony_ci struct notifier_block nb; 17862306a36Sopenharmony_ci struct mlx5_core_dev *mdev; 17962306a36Sopenharmony_ci}; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cienum { 18262306a36Sopenharmony_ci MLX5VF_QUERY_INC = (1UL << 0), 18362306a36Sopenharmony_ci MLX5VF_QUERY_FINAL = (1UL << 1), 18462306a36Sopenharmony_ci}; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ciint mlx5vf_cmd_suspend_vhca(struct mlx5vf_pci_core_device *mvdev, u16 op_mod); 18762306a36Sopenharmony_ciint mlx5vf_cmd_resume_vhca(struct mlx5vf_pci_core_device *mvdev, u16 op_mod); 18862306a36Sopenharmony_ciint mlx5vf_cmd_query_vhca_migration_state(struct mlx5vf_pci_core_device *mvdev, 18962306a36Sopenharmony_ci size_t *state_size, u8 query_flags); 19062306a36Sopenharmony_civoid mlx5vf_cmd_set_migratable(struct mlx5vf_pci_core_device *mvdev, 19162306a36Sopenharmony_ci const struct vfio_migration_ops *mig_ops, 19262306a36Sopenharmony_ci const struct vfio_log_ops *log_ops); 19362306a36Sopenharmony_civoid mlx5vf_cmd_remove_migratable(struct mlx5vf_pci_core_device *mvdev); 19462306a36Sopenharmony_civoid mlx5vf_cmd_close_migratable(struct mlx5vf_pci_core_device *mvdev); 19562306a36Sopenharmony_ciint mlx5vf_cmd_save_vhca_state(struct mlx5vf_pci_core_device *mvdev, 19662306a36Sopenharmony_ci struct mlx5_vf_migration_file *migf, 19762306a36Sopenharmony_ci struct mlx5_vhca_data_buffer *buf, bool inc, 19862306a36Sopenharmony_ci bool track); 19962306a36Sopenharmony_ciint mlx5vf_cmd_load_vhca_state(struct mlx5vf_pci_core_device *mvdev, 20062306a36Sopenharmony_ci struct mlx5_vf_migration_file *migf, 20162306a36Sopenharmony_ci struct mlx5_vhca_data_buffer *buf); 20262306a36Sopenharmony_ciint mlx5vf_cmd_alloc_pd(struct mlx5_vf_migration_file *migf); 20362306a36Sopenharmony_civoid mlx5vf_cmd_dealloc_pd(struct mlx5_vf_migration_file *migf); 20462306a36Sopenharmony_civoid mlx5fv_cmd_clean_migf_resources(struct mlx5_vf_migration_file *migf); 20562306a36Sopenharmony_cistruct mlx5_vhca_data_buffer * 20662306a36Sopenharmony_cimlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, 20762306a36Sopenharmony_ci size_t length, enum dma_data_direction dma_dir); 20862306a36Sopenharmony_civoid mlx5vf_free_data_buffer(struct mlx5_vhca_data_buffer *buf); 20962306a36Sopenharmony_cistruct mlx5_vhca_data_buffer * 21062306a36Sopenharmony_cimlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, 21162306a36Sopenharmony_ci size_t length, enum dma_data_direction dma_dir); 21262306a36Sopenharmony_civoid mlx5vf_put_data_buffer(struct mlx5_vhca_data_buffer *buf); 21362306a36Sopenharmony_ciint mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf, 21462306a36Sopenharmony_ci unsigned int npages); 21562306a36Sopenharmony_cistruct page *mlx5vf_get_migration_page(struct mlx5_vhca_data_buffer *buf, 21662306a36Sopenharmony_ci unsigned long offset); 21762306a36Sopenharmony_civoid mlx5vf_state_mutex_unlock(struct mlx5vf_pci_core_device *mvdev); 21862306a36Sopenharmony_civoid mlx5vf_disable_fds(struct mlx5vf_pci_core_device *mvdev); 21962306a36Sopenharmony_civoid mlx5vf_mig_file_cleanup_cb(struct work_struct *_work); 22062306a36Sopenharmony_ciint mlx5vf_start_page_tracker(struct vfio_device *vdev, 22162306a36Sopenharmony_ci struct rb_root_cached *ranges, u32 nnodes, u64 *page_size); 22262306a36Sopenharmony_ciint mlx5vf_stop_page_tracker(struct vfio_device *vdev); 22362306a36Sopenharmony_ciint mlx5vf_tracker_read_and_clear(struct vfio_device *vdev, unsigned long iova, 22462306a36Sopenharmony_ci unsigned long length, struct iova_bitmap *dirty); 22562306a36Sopenharmony_ci#endif /* MLX5_VFIO_CMD_H */ 226