mlx5 VFIO PCI DMA conversion
Subsystems (4)
cover mlx5 VFIO PCI DMA conversion
Hi Alex,
This series presents subset of new DMA-API patchset [1] specific for VFIO subsystem, with some small changes:
1. Change commit message in first patch.
2. Removed WARN_ON_ONCE DMA_NONE checks from third patch.
------------------------------------------------------------------
It is based on Marek's dma-mapping-for-6.16-two-step-api branch, so merging now will allow us to reduce possible rebase errors in mlx5 vfio code and give enough time to start to work on second driver conversion. Such conversion will allow us to generalize the API for VFIO kernel drivers, in similar way that was done for RDMA, HMM and block layers.
Thanks
[1] [PATCH v10 00/24] Provide a new two step DMA mapping API
https://lore.kernel.org/all/[email protected]/
Leon Romanovsky (3):
vfio/mlx5: Explicitly use number of pages instead of allocated length vfio/mlx5: Rewrite create mkey flow to allow better code reuse vfio/mlx5: Enable the DMA link API
drivers/vfio/pci/mlx5/cmd.c | 371 +++++++++++++++++------------------ drivers/vfio/pci/mlx5/cmd.h | 35 ++-- drivers/vfio/pci/mlx5/main.c | 87 ++++---- 3 files changed, 235 insertions(+), 258 deletions(-)
Signature · 1 line
2.49.0
PATCH 1/3 vfio/mlx5: Explicitly use number of pages instead of allocated length
From: Leon Romanovsky <[email protected]>
allocated_length is a multiple of page size and number of pages, so let's change the functions to accept number of pages. This improves code readability, simplifies buffer handling, and enables combining DMA send/receive operations, as will be introduced in the next patches.
--- drivers/vfio/pci/mlx5/cmd.c | 32 ++++++++++----------- drivers/vfio/pci/mlx5/cmd.h | 10 +++---- drivers/vfio/pci/mlx5/main.c | 56 +++++++++++++++++++++++------------- 3 files changed, 57 insertions(+), 41 deletions(-)
drivers/vfio/pci/mlx5/cmd.c +16 -16
@@ -318,8 +318,7 @@ static int _create_mkey(struct mlx5_core_dev *mdev, u32 pdn,struct mlx5_vhca_recv_buf *recv_buf, u32 *mkey) { - size_t npages = buf ? DIV_ROUND_UP(buf->allocated_length, PAGE_SIZE) : - recv_buf->npages; + size_t npages = buf ? buf->npages : recv_buf->npages;int err =0 , inlen;__be64 *mtt;void *mkc;
@@ -375,7 +374,7 @@ static int mlx5vf_dma_data_buffer(struct mlx5_vhca_data_buffer *buf)if (mvdev->mdev_detach)return -ENOTCONN ; -if (buf->dmaed || !buf->allocated_length) +if (buf->dmaed || !buf->npages)return -EINVAL ; ret =dma_map_sgtable (mdev->device, &buf->table.sgt, buf->dma_dir,0 );
@@ -445,7 +444,7 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf,if (ret) goto err_append; - buf->allocated_length += filled *PAGE_SIZE ; + buf->npages += filled;/* clean input for another bulk allocation */ memset (page_list,0 , filled *sizeof (*page_list)); to_fill = min_t(unsigned int, to_alloc,
@@ -464,8 +463,7 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf, }struct mlx5_vhca_data_buffer * -mlx5vf_alloc_data_buffer (struct mlx5_vf_migration_file *migf, -size_t length, +mlx5vf_alloc_data_buffer (struct mlx5_vf_migration_file *migf,u32 npages,enum dma_data_direction dma_dir) {struct mlx5_vhca_data_buffer *buf;
@@ -477,9 +475,8 @@ mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, buf->dma_dir = dma_dir; buf->migf = migf; -if (length) { - ret =mlx5vf_add_migration_pages (buf, -DIV_ROUND_UP_ULL (length,PAGE_SIZE )); +if (npages) { + ret =mlx5vf_add_migration_pages (buf, npages);if (ret) goto end;
@@ -505,8 +502,8 @@ void mlx5vf_put_data_buffer(struct mlx5_vhca_data_buffer *buf) }struct mlx5_vhca_data_buffer * -mlx5vf_get_data_buffer (struct mlx5_vf_migration_file *migf, -size_t length,enum dma_data_direction dma_dir) +mlx5vf_get_data_buffer (struct mlx5_vf_migration_file *migf,u32 npages, +enum dma_data_direction dma_dir) {struct mlx5_vhca_data_buffer *buf, *temp_buf;struct list_head free_list;
@@ -521,7 +518,7 @@ mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf,list_for_each_entry_safe (buf, temp_buf, &migf->avail_list, buf_elm) {if (buf->dma_dir == dma_dir) {list_del_init (&buf->buf_elm); -if (buf->allocated_length >= length) { +if (buf->npages >= npages) {spin_unlock_irq (&migf->list_lock); goto found; }
@@ -535,7 +532,7 @@ mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, } }spin_unlock_irq (&migf->list_lock); - buf =mlx5vf_alloc_data_buffer (migf, length, dma_dir); + buf =mlx5vf_alloc_data_buffer (migf, npages, dma_dir); found: while ((temp_buf = list_first_entry_or_null(&free_list,
@@ -716,7 +713,7 @@ int mlx5vf_cmd_save_vhca_state(struct mlx5vf_pci_core_device *mvdev,MLX5_SET (save_vhca_state_in, in, op_mod,0 );MLX5_SET (save_vhca_state_in, in, vhca_id, mvdev->vhca_id);MLX5_SET (save_vhca_state_in, in, mkey, buf->mkey); -MLX5_SET (save_vhca_state_in, in, size, buf->allocated_length); +MLX5_SET (save_vhca_state_in, in, size, buf->npages *PAGE_SIZE );MLX5_SET (save_vhca_state_in, in, incremental, inc);MLX5_SET (save_vhca_state_in, in, set_track, track);
@@ -738,8 +735,11 @@ int mlx5vf_cmd_save_vhca_state(struct mlx5vf_pci_core_device *mvdev, }if (!header_buf) { - header_buf =mlx5vf_get_data_buffer (migf, -sizeof (struct mlx5_vf_migration_header ),DMA_NONE ); + header_buf =mlx5vf_get_data_buffer ( + migf, +DIV_ROUND_UP (sizeof (struct mlx5_vf_migration_header ), +PAGE_SIZE ), +DMA_NONE );if (IS_ERR (header_buf)) { err =PTR_ERR (header_buf); goto err_free;
drivers/vfio/pci/mlx5/cmd.h +5 -5
@@ -56,7 +56,7 @@ struct mlx5_vhca_data_buffer {struct sg_append_table table;loff_t start_pos;u64 length; -u64 allocated_length; +u32 npages;u32 mkey;enum dma_data_direction dma_dir; u8 dmaed:1;
@@ -217,12 +217,12 @@ int mlx5vf_cmd_alloc_pd(struct mlx5_vf_migration_file *migf);void mlx5vf_cmd_dealloc_pd (struct mlx5_vf_migration_file *migf);void mlx5fv_cmd_clean_migf_resources (struct mlx5_vf_migration_file *migf);struct mlx5_vhca_data_buffer * -mlx5vf_alloc_data_buffer (struct mlx5_vf_migration_file *migf, -size_t length,enum dma_data_direction dma_dir); +mlx5vf_alloc_data_buffer (struct mlx5_vf_migration_file *migf,u32 npages, +enum dma_data_direction dma_dir);void mlx5vf_free_data_buffer (struct mlx5_vhca_data_buffer *buf);struct mlx5_vhca_data_buffer * -mlx5vf_get_data_buffer (struct mlx5_vf_migration_file *migf, -size_t length,enum dma_data_direction dma_dir); +mlx5vf_get_data_buffer (struct mlx5_vf_migration_file *migf,u32 npages, +enum dma_data_direction dma_dir);void mlx5vf_put_data_buffer (struct mlx5_vhca_data_buffer *buf);struct page *mlx5vf_get_migration_page (struct mlx5_vhca_data_buffer *buf,unsigned long offset);
drivers/vfio/pci/mlx5/main.c +36 -20
142 lines not on this page · raw message
Signature · 1 line
2.49.0
PATCH 2/3 vfio/mlx5: Rewrite create mkey flow to allow better code reuse
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Change the creation of mkey to be performed in multiple steps:
data allocation, DMA setup and actual call to HW to create that mkey.
In this new flow, the whole input to MKEY command is saved to eliminate the need to keep array of pointers for DMA addresses for receive list and in the future patches for send list too.
In addition to memory size reduce and elimination of unnecessary data movements to set MKEY input, the code is prepared for future reuse.
--- drivers/vfio/pci/mlx5/cmd.c | 157 ++++++++++++++++++++---------------- drivers/vfio/pci/mlx5/cmd.h | 4 +- 2 files changed, 91 insertions(+), 70 deletions(-)
drivers/vfio/pci/mlx5/cmd.c +89 -68
@@ -313,39 +313,21 @@ static int mlx5vf_cmd_get_vhca_id(struct mlx5_core_dev *mdev, u16 function_id,return ret; } -static int _create_mkey (struct mlx5_core_dev *mdev,u32 pdn, -struct mlx5_vhca_data_buffer *buf, -struct mlx5_vhca_recv_buf *recv_buf, -u32 *mkey) +static u32 *alloc_mkey_in (u32 npages,u32 pdn) { -size_t npages = buf ? buf->npages : recv_buf->npages; -int err =0 , inlen; -__be64 *mtt; +int inlen;void *mkc;u32 *in; inlen =MLX5_ST_SZ_BYTES (create_mkey_in) + -sizeof (*mtt) *round_up (npages,2 ); +sizeof (__be64) *round_up (npages,2 ); - in =kvzalloc (inlen,GFP_KERNEL ); + in =kvzalloc (inlen,GFP_KERNEL_ACCOUNT );if (!in) -return -ENOMEM ; +return NULL ;MLX5_SET (create_mkey_in, in, translations_octword_actual_size,DIV_ROUND_UP (npages,2 )); - mtt = (__be64 *)MLX5_ADDR_OF (create_mkey_in, in, klm_pas_mtt); - -if (buf) { -struct sg_dma_page_iter dma_iter; - -for_each_sgtable_dma_page (&buf->table.sgt, &dma_iter,0 ) - *mtt++ =cpu_to_be64 (sg_page_iter_dma_address (&dma_iter)); - }else { -int i; - -for (i =0 ; i < npages; i++) - *mtt++ =cpu_to_be64 (recv_buf->dma_addrs[i]); - } mkc =MLX5_ADDR_OF (create_mkey_in, in, memory_key_mkey_entry);MLX5_SET (mkc, mkc, access_mode_1_0,MLX5_MKC_ACCESS_MODE_MTT );
@@ -359,9 +341,30 @@ static int _create_mkey(struct mlx5_core_dev *mdev, u32 pdn,MLX5_SET (mkc, mkc, log_page_size,PAGE_SHIFT );MLX5_SET (mkc, mkc, translations_octword_size,DIV_ROUND_UP (npages,2 ));MLX5_SET64 (mkc, mkc, len, npages *PAGE_SIZE ); - err =mlx5_core_create_mkey (mdev, mkey, in, inlen); -kvfree (in); -return err; + +return in; +} + +static int create_mkey (struct mlx5_core_dev *mdev,u32 npages, +struct mlx5_vhca_data_buffer *buf,u32 *mkey_in, +u32 *mkey) +{ +__be64 *mtt; +int inlen; + + mtt = (__be64 *)MLX5_ADDR_OF (create_mkey_in, mkey_in, klm_pas_mtt); +if (buf) { +struct sg_dma_page_iter dma_iter; + +for_each_sgtable_dma_page (&buf->table.sgt, &dma_iter,0 ) + *mtt++ =cpu_to_be64 ( +sg_page_iter_dma_address (&dma_iter)); + } + + inlen =MLX5_ST_SZ_BYTES (create_mkey_in) + +sizeof (__be64) *round_up (npages,2 ); + +return mlx5_core_create_mkey (mdev, mkey, mkey_in, inlen); }static int mlx5vf_dma_data_buffer (struct mlx5_vhca_data_buffer *buf)
@@ -374,20 +377,28 @@ static int mlx5vf_dma_data_buffer(struct mlx5_vhca_data_buffer *buf)if (mvdev->mdev_detach)return -ENOTCONN ; -if (buf->dmaed || !buf->npages) +if (buf->mkey_in || !buf->npages)return -EINVAL ; ret =dma_map_sgtable (mdev->device, &buf->table.sgt, buf->dma_dir,0 );if (ret)return ret; - ret =_create_mkey (mdev, buf->migf->pdn, buf,NULL , &buf->mkey); -if (ret) + buf->mkey_in =alloc_mkey_in (buf->npages, buf->migf->pdn); +if (!buf->mkey_in) { + ret = -ENOMEM ; goto err; + } - buf->dmaed = true; + ret =create_mkey (mdev, buf->npages, buf, buf->mkey_in, &buf->mkey); +if (ret) + goto err_create_mkey;return 0 ; + +err_create_mkey: +kvfree (buf->mkey_in); + buf->mkey_in =NULL ; err:dma_unmap_sgtable (mdev->device, &buf->table.sgt, buf->dma_dir,0 );return ret;
@@ -401,8 +412,9 @@ void mlx5vf_free_data_buffer(struct mlx5_vhca_data_buffer *buf)lockdep_assert_held (&migf->mvdev->state_mutex);WARN_ON (migf->mvdev->mdev_detach); -if (buf->dmaed) { +if (buf->mkey_in) {mlx5_core_destroy_mkey (migf->mvdev->mdev, buf->mkey); +kvfree (buf->mkey_in);dma_unmap_sgtable (migf->mvdev->mdev->device, &buf->table.sgt, buf->dma_dir,0 ); }
@@ -783,7 +795,7 @@ int mlx5vf_cmd_load_vhca_state(struct mlx5vf_pci_core_device *mvdev,if (mvdev->mdev_detach)return -ENOTCONN ; -if (!buf->dmaed) { +if (!buf->mkey_in) { err =mlx5vf_dma_data_buffer (buf);if (err)return err;
@@ -1384,56 +1396,54 @@ static int alloc_recv_pages(struct mlx5_vhca_recv_buf *recv_buf,kvfree (recv_buf->page_list);return -ENOMEM ; } +static void unregister_dma_pages (struct mlx5_core_dev *mdev,u32 npages, +u32 *mkey_in) +{ +dma_addr_t addr; +__be64 *mtt; +int i; + + mtt = (__be64 *)MLX5_ADDR_OF (create_mkey_in, mkey_in, klm_pas_mtt); +for (i = npages -1 ; i >=0 ; i--) { + addr =be64_to_cpu (mtt[i]); +dma_unmap_single (mdev->device, addr,PAGE_SIZE , +DMA_FROM_DEVICE ); + } +} -static int register_dma_recv_pages (struct mlx5_core_dev *mdev, -struct mlx5_vhca_recv_buf *recv_buf) +static int register_dma_pages (struct mlx5_core_dev *mdev,u32 npages, +struct page **page_list,u32 *mkey_in) { -int i, j; +dma_addr_t addr; +__be64 *mtt; +int i; - recv_buf->dma_addrs =kvcalloc (recv_buf->npages, -sizeof (*recv_buf->dma_addrs), -GFP_KERNEL_ACCOUNT ); -if (!recv_buf->dma_addrs) -return -ENOMEM ; + mtt = (__be64 *)MLX5_ADDR_OF (create_mkey_in, mkey_in, klm_pas_mtt); -for (i =0 ; i < recv_buf->npages; i++) { - recv_buf->dma_addrs[i] =dma_map_page (mdev->device, - recv_buf->page_list[i], -0 ,PAGE_SIZE , -DMA_FROM_DEVICE ); -if (dma_mapping_error (mdev->device, recv_buf->dma_addrs[i])) +for (i =0 ; i < npages; i++) { + addr =dma_map_page (mdev->device, page_list[i],0 ,PAGE_SIZE , +DMA_FROM_DEVICE ); +if (dma_mapping_error (mdev->device, addr)) goto error; + + *mtt++ =cpu_to_be64 (addr); } +return 0 ; error: -for (j =0 ; j < i; j++) -dma_unmap_single (mdev->device, recv_buf->dma_addrs[j], -PAGE_SIZE ,DMA_FROM_DEVICE ); - -kvfree (recv_buf->dma_addrs); +unregister_dma_pages (mdev, i, mkey_in);return -ENOMEM ; } -static void unregister_dma_recv_pages (struct mlx5_core_dev *mdev, -struct mlx5_vhca_recv_buf *recv_buf) -{ -int i; - -for (i =0 ; i < recv_buf->npages; i++) -dma_unmap_single (mdev->device, recv_buf->dma_addrs[i], -PAGE_SIZE ,DMA_FROM_DEVICE ); - -kvfree (recv_buf->dma_addrs); -} -static void mlx5vf_free_qp_recv_resources (struct mlx5_core_dev *mdev,struct mlx5_vhca_qp *qp) {struct mlx5_vhca_recv_buf *recv_buf = &qp->recv_buf;mlx5_core_destroy_mkey (mdev, recv_buf->mkey); -unregister_dma_recv_pages (mdev, recv_buf); +unregister_dma_pages (mdev, recv_buf->npages, recv_buf->mkey_in); +kvfree (recv_buf->mkey_in);free_recv_pages (&qp->recv_buf); }
@@ -1449,18 +1459,29 @@ static int mlx5vf_alloc_qp_recv_resources(struct mlx5_core_dev *mdev,if (err <0 )return err; - err =register_dma_recv_pages (mdev, recv_buf); -if (err) + recv_buf->mkey_in =alloc_mkey_in (npages, pdn); +if (!recv_buf->mkey_in) { + err = -ENOMEM ; goto end; + } + + err =register_dma_pages (mdev, npages, recv_buf->page_list, + recv_buf->mkey_in); +if (err) + goto err_register_dma; - err =_create_mkey (mdev, pdn,NULL , recv_buf, &recv_buf->mkey); + err =create_mkey (mdev, npages,NULL , recv_buf->mkey_in, + &recv_buf->mkey);if (err) goto err_create_mkey;return 0 ; err_create_mkey: -unregister_dma_recv_pages (mdev, recv_buf); +unregister_dma_pages (mdev, npages, recv_buf->mkey_in); +err_register_dma: +kvfree (recv_buf->mkey_in); + recv_buf->mkey_in =NULL ; end:free_recv_pages (recv_buf);return err;
drivers/vfio/pci/mlx5/cmd.h +2 -2
@@ -58,8 +58,8 @@ struct mlx5_vhca_data_buffer {u64 length;u32 npages;u32 mkey; +u32 *mkey_in;enum dma_data_direction dma_dir; - u8 dmaed:1;u8 stop_copy_chunk_num;struct list_head buf_elm;struct mlx5_vf_migration_file *migf;
@@ -133,8 +133,8 @@ struct mlx5_vhca_cq {struct mlx5_vhca_recv_buf {u32 npages;struct page **page_list; -dma_addr_t *dma_addrs;u32 next_rq_offset; +u32 *mkey_in;u32 mkey; };
Signature · 1 line
2.49.0
PATCH 3/3 vfio/mlx5: Enable the DMA link API
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Remove intermediate scatter-gather table completely and enable new DMA link API.
--- drivers/vfio/pci/mlx5/cmd.c | 294 +++++++++++++++-------------------- drivers/vfio/pci/mlx5/cmd.h | 21 ++- drivers/vfio/pci/mlx5/main.c | 31 ---- 3 files changed, 143 insertions(+), 203 deletions(-)
drivers/vfio/pci/mlx5/cmd.c +129 -165
@@ -345,26 +345,78 @@ static u32 *alloc_mkey_in(u32 npages, u32 pdn)return in; } -static int create_mkey (struct mlx5_core_dev *mdev,u32 npages, -struct mlx5_vhca_data_buffer *buf,u32 *mkey_in, +static int create_mkey (struct mlx5_core_dev *mdev,u32 npages,u32 *mkey_in,u32 *mkey) { +int inlen =MLX5_ST_SZ_BYTES (create_mkey_in) + +sizeof (__be64) *round_up (npages,2 ); + +return mlx5_core_create_mkey (mdev, mkey, mkey_in, inlen); +} + +static void unregister_dma_pages (struct mlx5_core_dev *mdev,u32 npages, +u32 *mkey_in,struct dma_iova_state *state, +enum dma_data_direction dir) +{ +dma_addr_t addr;__be64 *mtt; -int inlen; +int i; + +if (dma_use_iova (state)) { +dma_iova_destroy (mdev->device, state, npages *PAGE_SIZE , dir, +0 ); + }else { + mtt = (__be64 *)MLX5_ADDR_OF (create_mkey_in, mkey_in, + klm_pas_mtt); +for (i = npages -1 ; i >=0 ; i--) { + addr =be64_to_cpu (mtt[i]); +dma_unmap_page (mdev->device, addr,PAGE_SIZE , dir); + } + } +} + +static int register_dma_pages (struct mlx5_core_dev *mdev,u32 npages, +struct page **page_list,u32 *mkey_in, +struct dma_iova_state *state, +enum dma_data_direction dir) +{ +dma_addr_t addr; +size_t mapped =0 ; +__be64 *mtt; +int i, err; mtt = (__be64 *)MLX5_ADDR_OF (create_mkey_in, mkey_in, klm_pas_mtt); -if (buf) { -struct sg_dma_page_iter dma_iter; -for_each_sgtable_dma_page (&buf->table.sgt, &dma_iter,0 ) - *mtt++ =cpu_to_be64 ( -sg_page_iter_dma_address (&dma_iter)); +if (dma_iova_try_alloc (mdev->device, state,0 , npages *PAGE_SIZE )) { + addr = state->addr; +for (i =0 ; i < npages; i++) { + err =dma_iova_link (mdev->device, state, +page_to_phys (page_list[i]), mapped, +PAGE_SIZE , dir,0 ); +if (err) + goto error; + *mtt++ =cpu_to_be64 (addr); + addr +=PAGE_SIZE ; + mapped +=PAGE_SIZE ; + } + err =dma_iova_sync (mdev->device, state,0 , mapped); +if (err) + goto error; + }else { +for (i =0 ; i < npages; i++) { + addr =dma_map_page (mdev->device, page_list[i],0 , +PAGE_SIZE , dir); + err =dma_mapping_error (mdev->device, addr); +if (err) + goto error; + *mtt++ =cpu_to_be64 (addr); + } } +return 0 ; - inlen =MLX5_ST_SZ_BYTES (create_mkey_in) + -sizeof (__be64) *round_up (npages,2 ); - -return mlx5_core_create_mkey (mdev, mkey, mkey_in, inlen); +error: +unregister_dma_pages (mdev, i, mkey_in, state, dir); +return err; }static int mlx5vf_dma_data_buffer (struct mlx5_vhca_data_buffer *buf)
@@ -380,98 +432,90 @@ static int mlx5vf_dma_data_buffer(struct mlx5_vhca_data_buffer *buf)if (buf->mkey_in || !buf->npages)return -EINVAL ; - ret =dma_map_sgtable (mdev->device, &buf->table.sgt, buf->dma_dir,0 ); -if (ret) -return ret; - buf->mkey_in =alloc_mkey_in (buf->npages, buf->migf->pdn); -if (!buf->mkey_in) { - ret = -ENOMEM ; - goto err; - } +if (!buf->mkey_in) +return -ENOMEM ; - ret =create_mkey (mdev, buf->npages, buf, buf->mkey_in, &buf->mkey); + ret =register_dma_pages (mdev, buf->npages, buf->page_list, + buf->mkey_in, &buf->state, buf->dma_dir); +if (ret) + goto err_register_dma; + + ret =create_mkey (mdev, buf->npages, buf->mkey_in, &buf->mkey);if (ret) goto err_create_mkey;return 0 ; err_create_mkey: +unregister_dma_pages (mdev, buf->npages, buf->mkey_in, &buf->state, + buf->dma_dir); +err_register_dma:kvfree (buf->mkey_in); buf->mkey_in =NULL ; -err: -dma_unmap_sgtable (mdev->device, &buf->table.sgt, buf->dma_dir,0 );return ret; } +static void free_page_list (u32 npages,struct page **page_list) +{ +int i; + +/* Undo alloc_pages_bulk() */ +for (i = npages -1 ; i >=0 ; i--) +__free_page (page_list[i]); + +kvfree (page_list); +} +void mlx5vf_free_data_buffer (struct mlx5_vhca_data_buffer *buf) { -struct mlx5_vf_migration_file *migf = buf->migf; -struct sg_page_iter sg_iter; +struct mlx5vf_pci_core_device *mvdev = buf->migf->mvdev; +struct mlx5_core_dev *mdev = mvdev->mdev; -lockdep_assert_held (&migf->mvdev->state_mutex); -WARN_ON (migf->mvdev->mdev_detach); +lockdep_assert_held (&mvdev->state_mutex); +WARN_ON (mvdev->mdev_detach);if (buf->mkey_in) { -mlx5_core_destroy_mkey (migf->mvdev->mdev, buf->mkey); +mlx5_core_destroy_mkey (mdev, buf->mkey); +unregister_dma_pages (mdev, buf->npages, buf->mkey_in, + &buf->state, buf->dma_dir);kvfree (buf->mkey_in); -dma_unmap_sgtable (migf->mvdev->mdev->device, &buf->table.sgt, - buf->dma_dir,0 ); } -/* Undo alloc_pages_bulk() */ -for_each_sgtable_page (&buf->table.sgt, &sg_iter,0 ) -__free_page (sg_page_iter_page (&sg_iter)); -sg_free_append_table (&buf->table); +free_page_list (buf->npages, buf->page_list);kfree (buf); } -static int mlx5vf_add_migration_pages (struct mlx5_vhca_data_buffer *buf, -unsigned int npages) +static int mlx5vf_add_pages (struct page ***page_list,unsigned int npages) { -unsigned int to_alloc = npages; -struct page **page_list; -unsigned long filled; -unsigned int to_fill; -int ret; +unsigned int filled, done =0 ;int i; - to_fill = min_t(unsigned int, npages, PAGE_SIZE / sizeof(*page_list)); - page_list =kvzalloc (to_fill *sizeof (*page_list),GFP_KERNEL_ACCOUNT ); -if (!page_list) + *page_list = +kvcalloc (npages,sizeof (struct page *),GFP_KERNEL_ACCOUNT ); +if (!*page_list)return -ENOMEM ; -do { - filled =alloc_pages_bulk (GFP_KERNEL_ACCOUNT , to_fill, - page_list); -if (!filled) { - ret = -ENOMEM ; +for (;;) { + filled =alloc_pages_bulk (GFP_KERNEL_ACCOUNT , npages - done, + *page_list + done); +if (!filled) goto err; - } - to_alloc -= filled; - ret =sg_alloc_append_table_from_pages ( - &buf->table, page_list, filled,0 , - filled <<PAGE_SHIFT ,UINT_MAX ,SG_MAX_SINGLE_ALLOC , -GFP_KERNEL_ACCOUNT ); -if (ret) - goto err_append; - buf->npages += filled; -/* clean input for another bulk allocation */ -memset (page_list,0 , filled *sizeof (*page_list)); - to_fill = min_t(unsigned int, to_alloc, -PAGE_SIZE /sizeof (*page_list)); - }while (to_alloc >0 ); + done += filled; +if (done == npages) +break ; + } -kvfree (page_list);return 0 ; -err_append: -for (i = filled -1 ; i >=0 ; i--) -__free_page (page_list[i]); err: -kvfree (page_list); -return ret; +for (i =0 ; i < done; i++) +__free_page (*page_list[i]); + +kvfree (*page_list); + *page_list =NULL ; +return -ENOMEM ; } struct mlx5_vhca_data_buffer *
@@ -488,10 +532,12 @@ mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf, u32 npages, buf->dma_dir = dma_dir; buf->migf = migf;if (npages) { - ret =mlx5vf_add_migration_pages (buf, npages); + ret =mlx5vf_add_pages (&buf->page_list, npages);if (ret) goto end; + buf->npages = npages; +if (dma_dir !=DMA_NONE ) { ret =mlx5vf_dma_data_buffer (buf);if (ret)
@@ -1350,101 +1396,16 @@ static void mlx5vf_destroy_qp(struct mlx5_core_dev *mdev,kfree (qp); } -static void free_recv_pages (struct mlx5_vhca_recv_buf *recv_buf) -{ -int i; - -/* Undo alloc_pages_bulk() */ -for (i =0 ; i < recv_buf->npages; i++) -__free_page (recv_buf->page_list[i]); - -kvfree (recv_buf->page_list); -} - -static int alloc_recv_pages (struct mlx5_vhca_recv_buf *recv_buf, -unsigned int npages) -{ -unsigned int filled =0 , done =0 ; -int i; - - recv_buf->page_list =kvcalloc (npages,sizeof (*recv_buf->page_list), -GFP_KERNEL_ACCOUNT ); -if (!recv_buf->page_list) -return -ENOMEM ; - -for (;;) { - filled =alloc_pages_bulk (GFP_KERNEL_ACCOUNT , - npages - done, - recv_buf->page_list + done); -if (!filled) - goto err; - - done += filled; -if (done == npages) -break ; - } - - recv_buf->npages = npages; -return 0 ; - -err: -for (i =0 ; i < npages; i++) { -if (recv_buf->page_list[i]) -__free_page (recv_buf->page_list[i]); - } - -kvfree (recv_buf->page_list); -return -ENOMEM ; -} -static void unregister_dma_pages (struct mlx5_core_dev *mdev,u32 npages, -u32 *mkey_in) -{ -dma_addr_t addr; -__be64 *mtt; -int i; - - mtt = (__be64 *)MLX5_ADDR_OF (create_mkey_in, mkey_in, klm_pas_mtt); -for (i = npages -1 ; i >=0 ; i--) { - addr =be64_to_cpu (mtt[i]); -dma_unmap_single (mdev->device, addr,PAGE_SIZE , -DMA_FROM_DEVICE ); - } -} - -static int register_dma_pages (struct mlx5_core_dev *mdev,u32 npages, -struct page **page_list,u32 *mkey_in) -{ -dma_addr_t addr; -__be64 *mtt; -int i; - - mtt = (__be64 *)MLX5_ADDR_OF (create_mkey_in, mkey_in, klm_pas_mtt); - -for (i =0 ; i < npages; i++) { - addr =dma_map_page (mdev->device, page_list[i],0 ,PAGE_SIZE , -DMA_FROM_DEVICE ); -if (dma_mapping_error (mdev->device, addr)) - goto error; - - *mtt++ =cpu_to_be64 (addr); - } - -return 0 ; - -error: -unregister_dma_pages (mdev, i, mkey_in); -return -ENOMEM ; -} -static void mlx5vf_free_qp_recv_resources (struct mlx5_core_dev *mdev,struct mlx5_vhca_qp *qp) {struct mlx5_vhca_recv_buf *recv_buf = &qp->recv_buf;mlx5_core_destroy_mkey (mdev, recv_buf->mkey); -unregister_dma_pages (mdev, recv_buf->npages, recv_buf->mkey_in); +unregister_dma_pages (mdev, recv_buf->npages, recv_buf->mkey_in, + &recv_buf->state,DMA_FROM_DEVICE );kvfree (recv_buf->mkey_in); -free_recv_pages (&qp->recv_buf); +free_page_list (recv_buf->npages, recv_buf->page_list); } static int mlx5vf_alloc_qp_recv_resources(struct mlx5_core_dev *mdev,
@@ -1455,10 +1416,12 @@ static int mlx5vf_alloc_qp_recv_resources(struct mlx5_core_dev *mdev,struct mlx5_vhca_recv_buf *recv_buf = &qp->recv_buf;int err; - err =alloc_recv_pages (recv_buf, npages); -if (err <0 ) + err =mlx5vf_add_pages (&recv_buf->page_list, npages); +if (err)return err; + recv_buf->npages = npages; + recv_buf->mkey_in =alloc_mkey_in (npages, pdn);if (!recv_buf->mkey_in) { err = -ENOMEM ;
@@ -1466,24 +1429,25 @@ static int mlx5vf_alloc_qp_recv_resources(struct mlx5_core_dev *mdev, } err =register_dma_pages (mdev, npages, recv_buf->page_list, - recv_buf->mkey_in); + recv_buf->mkey_in, &recv_buf->state, +DMA_FROM_DEVICE );if (err) goto err_register_dma; - err =create_mkey (mdev, npages,NULL , recv_buf->mkey_in, - &recv_buf->mkey); + err =create_mkey (mdev, npages, recv_buf->mkey_in, &recv_buf->mkey);if (err) goto err_create_mkey;return 0 ; err_create_mkey: -unregister_dma_pages (mdev, npages, recv_buf->mkey_in); +unregister_dma_pages (mdev, npages, recv_buf->mkey_in, &recv_buf->state, +DMA_FROM_DEVICE ); err_register_dma:kvfree (recv_buf->mkey_in); recv_buf->mkey_in =NULL ; end: -free_recv_pages (recv_buf); +free_page_list (npages, recv_buf->page_list);return err; }
drivers/vfio/pci/mlx5/cmd.h +14 -7
@@ -53,7 +53,8 @@ struct mlx5_vf_migration_header { };struct mlx5_vhca_data_buffer { -struct sg_append_table table; +struct page **page_list; +struct dma_iova_state state;loff_t start_pos;u64 length;u32 npages;
@@ -63,10 +64,6 @@ struct mlx5_vhca_data_buffer {u8 stop_copy_chunk_num;struct list_head buf_elm;struct mlx5_vf_migration_file *migf; -/* Optimize mlx5vf_get_migration_page() for sequential access */ -struct scatterlist *last_offset_sg; -unsigned int sg_last_entry; -unsigned long last_offset; };struct mlx5vf_async_data {
@@ -133,6 +130,7 @@ struct mlx5_vhca_cq {struct mlx5_vhca_recv_buf {u32 npages;struct page **page_list; +struct dma_iova_state state;u32 next_rq_offset;u32 *mkey_in;u32 mkey;
@@ -224,8 +222,17 @@ struct mlx5_vhca_data_buffer * mlx5vf_get_data_buffer(struct mlx5_vf_migration_file *migf, u32 npages, enum dma_data_direction dma_dir);void mlx5vf_put_data_buffer (struct mlx5_vhca_data_buffer *buf); -struct page *mlx5vf_get_migration_page (struct mlx5_vhca_data_buffer *buf, -unsigned long offset); +static inline struct page * +mlx5vf_get_migration_page (struct mlx5_vhca_data_buffer *buf, +unsigned long offset) +{ +int page_entry = offset /PAGE_SIZE ; + +if (page_entry >= buf->npages) +return NULL ; + +return buf->page_list[page_entry]; +}void mlx5vf_state_mutex_unlock (struct mlx5vf_pci_core_device *mvdev);void mlx5vf_disable_fds (struct mlx5vf_pci_core_device *mvdev,enum mlx5_vf_migf_state *last_save_state);
drivers/vfio/pci/mlx5/main.c +0 -31
@@ -34,37 +34,6 @@ static struct mlx5vf_pci_core_device *mlx5vf_drvdata(struct pci_dev *pdev) core_device); } -struct page * -mlx5vf_get_migration_page (struct mlx5_vhca_data_buffer *buf, -unsigned long offset) -{ -unsigned long cur_offset =0 ; -struct scatterlist *sg; -unsigned int i; - -/* All accesses are sequential */ -if (offset < buf->last_offset || !buf->last_offset_sg) { - buf->last_offset =0 ; - buf->last_offset_sg = buf->table.sgt.sgl; - buf->sg_last_entry =0 ; - } - - cur_offset = buf->last_offset; - -for_each_sg (buf->last_offset_sg, sg, - buf->table.sgt.orig_nents - buf->sg_last_entry, i) { -if (offset < sg->length + cur_offset) { - buf->last_offset_sg = sg; - buf->sg_last_entry += i; - buf->last_offset = cur_offset; -return nth_page (sg_page (sg), - (offset - cur_offset) /PAGE_SIZE ); - } - cur_offset += sg->length; - } -return NULL ; -} -static void mlx5vf_disable_fd (struct mlx5_vf_migration_file *migf) {mutex_lock (&migf->lock);
Signature · 1 line
2.49.0
Quoted 24 lines · Leon Romanovsky
Hi Alex,
This series presents subset of new DMA-API patchset [1] specific for VFIO subsystem, with some small changes:
1. Change commit message in first patch.
2. RemovedWARN_ON_ONCEDMA_NONEchecks from third patch.------------------------------------------------------------------
It is based on Marek's dma-mapping-for-6.16-two-step-api branch, so merging now will allow us to reduce possible rebase errors in mlx5 vfio code and give enough time to start to work on second driver conversion. Such conversion will allow us to generalize the API for VFIO kernel drivers, in similar way that was done for RDMA, HMM and block layers.Thanks
[1] [PATCH v10 00/24] Provide a new two step DMA mapping API
https://lore.kernel.org/all/[email protected]/Leon Romanovsky (3):
vfio/mlx5: Explicitly use number of pages instead of allocated length vfio/mlx5: Rewrite create mkey flow to allow better code reuse vfio/mlx5: Enable the DMA link API
Quoted 5 lines
drivers/vfio/pci/mlx5/cmd.c | 371 +++++++++++++++++------------------ drivers/vfio/pci/mlx5/cmd.h | 35 ++-- drivers/vfio/pci/mlx5/main.c | 87 ++++---- 3 files changed, 235 insertions(+), 258 deletions(-)
The series looks good to me.
Alex Williamson
AppliedQuoted 24 lines · On Tue, 20 May 2025 16:46:29 +0300 Leon Romanovsky <[email protected]> wrote:
Hi Alex,
This series presents subset of new DMA-API patchset [1] specific for VFIO subsystem, with some small changes:
1. Change commit message in first patch.
2. RemovedWARN_ON_ONCEDMA_NONEchecks from third patch.------------------------------------------------------------------
It is based on Marek's dma-mapping-for-6.16-two-step-api branch, so merging now will allow us to reduce possible rebase errors in mlx5 vfio code and give enough time to start to work on second driver conversion. Such conversion will allow us to generalize the API for VFIO kernel drivers, in similar way that was done for RDMA, HMM and block layers.Thanks
[1] [PATCH v10 00/24] Provide a new two step DMA mapping API
https://lore.kernel.org/all/[email protected]/Leon Romanovsky (3):
vfio/mlx5: Explicitly use number of pages instead of allocated length vfio/mlx5: Rewrite create mkey flow to allow better code reuse vfio/mlx5: Enable the DMA link API
Quoted 4 lines
drivers/vfio/pci/mlx5/cmd.c | 371 +++++++++++++++++------------------ drivers/vfio/pci/mlx5/cmd.h | 35 ++-- drivers/vfio/pci/mlx5/main.c | 87 ++++---- 3 files changed, 235 insertions(+), 258 deletions(-)
Applied to vfio next branch for v6.16. Thanks,
Alex