ODP Fixes and Improvements
Subsystems (11)
cover ODP Fixes and Improvements
Hi Doug,
Please find the following patch set from Artemy. This patch set fixes and extends ODP support.
This patch set has the following steps:
1. Code simplification for all IB drivers.
2. Three fixes to existing ODP code.
3. Adds generic infrastructure for regions consisting of physically contiguous chunks of arbitrary order. Utilizing this infrastructure added specific treatment to ODP MRs allocated with MAP_HUGETLB.
4. Adds ODP suport to Memory Windows (MW). Memory windows allow the application to have more flexible control over access to its memory. The operation of associating an MW with an MR is called binding. When MW is bound to ODP MR it may cause page fault which should be properly handled.
Thanks
Artemy Kovalyov (10):
IB: Replace ib_umem page_size by page_shift IB/mlx5: Fix function updating xlt emergency path IB/mlx5: Fix UMR size calculation IB/mlx5: Fix implicit MR GC
IB/mlx5: Decrease verbosity level of ODP errors IB/umem: Add contiguous ODP support IB/mlx5: Add contiguous ODP support IB/umem: Add support to huge ODP
IB/mlx5: Extract page fault code
IB/mlx5: Add ODP support to MW
drivers/infiniband/core/umem.c | 17 +- drivers/infiniband/core/umem_odp.c | 81 ++++-- drivers/infiniband/hw/bnxt_re/ib_verbs.c | 12 +- drivers/infiniband/hw/cxgb3/iwch_provider.c | 4 +- drivers/infiniband/hw/cxgb4/mem.c | 4 +- drivers/infiniband/hw/hns/hns_roce_cq.c | 3 +- drivers/infiniband/hw/hns/hns_roce_mr.c | 9 +- drivers/infiniband/hw/hns/hns_roce_qp.c | 3 +- drivers/infiniband/hw/i40iw/i40iw_verbs.c | 7 +- drivers/infiniband/hw/mlx4/cq.c | 2 +- drivers/infiniband/hw/mlx4/mr.c | 6 +- drivers/infiniband/hw/mlx4/qp.c | 2 +- drivers/infiniband/hw/mlx4/srq.c | 2 +- drivers/infiniband/hw/mlx5/mem.c | 13 +- drivers/infiniband/hw/mlx5/mlx5_ib.h | 1 + drivers/infiniband/hw/mlx5/mr.c | 6 +- drivers/infiniband/hw/mlx5/odp.c | 344 +++++++++++++++---------- drivers/infiniband/hw/mthca/mthca_provider.c | 5 +- drivers/infiniband/hw/nes/nes_verbs.c | 4 +- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 15 +- drivers/infiniband/hw/qedr/verbs.c | 8 +- drivers/infiniband/hw/vmw_pvrdma/pvrdma_misc.c | 2 +- drivers/infiniband/sw/rdmavt/mr.c | 8 +- drivers/infiniband/sw/rxe/rxe_mr.c | 8 +- include/rdma/ib_umem.h | 8 +- include/rdma/ib_umem_odp.h | 6 +- include/rdma/ib_verbs.h | 1 + 27 files changed, 337 insertions(+), 244 deletions(-)
--
2.12.0
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20170403100640.3332-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
PATCH 1/10 IB: Replace ib_umem page_size by page_shift
From: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Size of pages are held by struct ib_umem in page_size field.
It is better to store it as an exponent, because page size by nature is always power-of-two and used as a factor, divisor or ilog2's argument.
The conversion of page_size to be page_shift allows to have portable code and avoid following error while compiling on ARM:
ERROR: "__aeabi_uldivmod" [drivers/infiniband/core/ib_core.ko] undefined!
--- drivers/infiniband/core/umem.c | 15 ++++++--------- drivers/infiniband/core/umem_odp.c | 12 ++++++------ drivers/infiniband/hw/bnxt_re/ib_verbs.c | 12 ++++++------ drivers/infiniband/hw/cxgb3/iwch_provider.c | 4 ++-- drivers/infiniband/hw/cxgb4/mem.c | 4 ++-- drivers/infiniband/hw/hns/hns_roce_cq.c | 3 +-- drivers/infiniband/hw/hns/hns_roce_mr.c | 9 +++++---- drivers/infiniband/hw/hns/hns_roce_qp.c | 3 +-- drivers/infiniband/hw/i40iw/i40iw_verbs.c | 7 ++++--- drivers/infiniband/hw/mlx4/cq.c | 2 +- drivers/infiniband/hw/mlx4/mr.c | 6 +++--- drivers/infiniband/hw/mlx4/qp.c | 2 +- drivers/infiniband/hw/mlx4/srq.c | 2 +- drivers/infiniband/hw/mlx5/mem.c | 4 ++-- drivers/infiniband/hw/mlx5/odp.c | 2 +- drivers/infiniband/hw/mthca/mthca_provider.c | 5 ++--- drivers/infiniband/hw/nes/nes_verbs.c | 4 ++-- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 15 ++++++--------- drivers/infiniband/hw/qedr/verbs.c | 8 ++++---- drivers/infiniband/hw/vmw_pvrdma/pvrdma_misc.c | 2 +- drivers/infiniband/sw/rdmavt/mr.c | 8 ++++---- drivers/infiniband/sw/rxe/rxe_mr.c | 8 +++----- include/rdma/ib_umem.h | 4 ++-- 23 files changed, 66 insertions(+), 75 deletions(-)
drivers/infiniband/core/umem.c +6 -9
@@ -115,11 +115,11 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,if (!umem)return ERR_PTR (-ENOMEM ); - umem->context = context; - umem->length = size; - umem->address = addr; - umem->page_size =PAGE_SIZE ; - umem->pid =get_task_pid (current,PIDTYPE_PID ); + umem->context = context; + umem->length = size; + umem->address = addr; + umem->page_shift =PAGE_SHIFT ; + umem->pid =get_task_pid (current,PIDTYPE_PID );/* * We ask for writable memory if any of the following * access flags are set. "Local write" and "remote write"
@@ -315,7 +315,6 @@ EXPORT_SYMBOL(ib_umem_release);int ib_umem_page_count (struct ib_umem *umem) { -int shift;int i;int n;struct scatterlist *sg;
@@ -323,11 +322,9 @@ int ib_umem_page_count(struct ib_umem *umem)if (umem->odp_data)return ib_umem_num_pages (umem); - shift =ilog2 (umem->page_size); - n =0 ;for_each_sg (umem->sg_head.sgl, sg, umem->nmap, i) - n +=sg_dma_len (sg) >> shift; + n +=sg_dma_len (sg) >> umem->page_shift;return n; }
drivers/infiniband/core/umem_odp.c +6 -6
@@ -254,11 +254,11 @@ struct ib_umem *ib_alloc_odp_umem(struct ib_ucontext *context,if (!umem)return ERR_PTR (-ENOMEM ); - umem->context = context; - umem->length = size; - umem->address = addr; - umem->page_size =PAGE_SIZE ; - umem->writable =1 ; + umem->context = context; + umem->length = size; + umem->address = addr; + umem->page_shift =PAGE_SHIFT ; + umem->writable =1 ; odp_data =kzalloc (sizeof (*odp_data),GFP_KERNEL );if (!odp_data) {
@@ -707,7 +707,7 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem *umem, u64 virt,* invalidations, so we must make sure we free each page only * once. */ mutex_lock (&umem->odp_data->umem_mutex); -for (addr = virt; addr < bound; addr += (u64 )umem->page_size) { +for (addr = virt; addr < bound; addr +=BIT (umem->page_shift)) { idx = (addr -ib_umem_start (umem)) /PAGE_SIZE ;if (umem->odp_data->page_list[idx]) {struct page *page = umem->odp_data->page_list[idx];
drivers/infiniband/hw/bnxt_re/ib_verbs.c +6 -6
@@ -3016,7 +3016,7 @@ struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length,struct bnxt_re_mr *mr;struct ib_umem *umem;u64 *pbl_tbl, *pbl_tbl_orig; -int i, umem_pgs, pages, page_shift, rc; +int i, umem_pgs, pages, rc;struct scatterlist *sg;int entry;
@@ -3062,22 +3062,22 @@ struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length, } pbl_tbl_orig = pbl_tbl; - page_shift =ilog2 (umem->page_size);if (umem->hugetlb) {dev_err (rdev_to_dev (rdev),"umem hugetlb not supported!" ); rc = -EFAULT ; goto fail; } -if (umem->page_size !=PAGE_SIZE ) { -dev_err (rdev_to_dev (rdev),"umem page size unsupported!" ); + +if (umem->page_shift !=PAGE_SHIFT ) { +dev_err (rdev_to_dev (rdev),"umem page shift unsupported!" ); rc = -EFAULT ; goto fail; }/* Map umem buf ptrs to the PBL */ for_each_sg (umem->sg_head.sgl, sg, umem->nmap, entry) { - pages =sg_dma_len (sg) >> page_shift; + pages =sg_dma_len (sg) >> umem->page_shift;for (i =0 ; i < pages; i++, pbl_tbl++) - *pbl_tbl =sg_dma_address (sg) + (i << page_shift); + *pbl_tbl =sg_dma_address (sg) + (i << umem->page_shift); } rc =bnxt_qplib_reg_mr (&rdev->qplib_res, &mr->qplib_mr, pbl_tbl_orig, umem_pgs, false);
drivers/infiniband/hw/cxgb3/iwch_provider.c +2 -2
@@ -584,7 +584,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,return ERR_PTR (err); } - shift =ffs (mhp->umem->page_size) -1 ; + shift = mhp->umem->page_shift; n = mhp->umem->nmap;
@@ -604,7 +604,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, len =sg_dma_len (sg) >> shift;for (k =0 ; k < len; ++k) { pages[i++] =cpu_to_be64 (sg_dma_address (sg) + - mhp->umem->page_size * k); + (k << shift));if (i ==PAGE_SIZE /sizeof *pages) { err =iwch_write_pbl (mhp, pages, i, n);if (err)
drivers/infiniband/hw/cxgb4/mem.c +2 -2
@@ -517,7 +517,7 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,return ERR_PTR (err); } - shift =ffs (mhp->umem->page_size) -1 ; + shift = mhp->umem->page_shift; n = mhp->umem->nmap; err =alloc_pbl (mhp, n);
@@ -536,7 +536,7 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, len =sg_dma_len (sg) >> shift;for (k =0 ; k < len; ++k) { pages[i++] =cpu_to_be64 (sg_dma_address (sg) + - mhp->umem->page_size * k); + (k << shift));if (i ==PAGE_SIZE /sizeof *pages) { err = write_pbl(&mhp->rhp->rdev, pages,
drivers/infiniband/hw/hns/hns_roce_cq.c +1 -2
@@ -219,8 +219,7 @@ static int hns_roce_ib_get_cq_umem(struct hns_roce_dev *hr_dev,return PTR_ERR (*umem); ret =hns_roce_mtt_init (hr_dev,ib_umem_page_count (*umem), -ilog2 ((unsigned int )(*umem)->page_size), - &buf->hr_mtt); + (*umem)->page_shift, &buf->hr_mtt);if (ret) goto err_buf;
drivers/infiniband/hw/hns/hns_roce_mr.c +5 -4
@@ -503,7 +503,8 @@ int hns_roce_ib_umem_write_mtt(struct hns_roce_dev *hr_dev,for_each_sg (umem->sg_head.sgl, sg, umem->nmap, entry) { len =sg_dma_len (sg) >> mtt->page_shift;for (k =0 ; k < len; ++k) { - pages[i++] =sg_dma_address (sg) + umem->page_size * k; + pages[i++] =sg_dma_address (sg) + + (k << umem->page_shift);if (i ==PAGE_SIZE /sizeof (u64)) { ret =hns_roce_write_mtt (hr_dev, mtt, n, i, pages);
@@ -563,9 +564,9 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, } n =ib_umem_page_count (mr->umem); -if (mr->umem->page_size !=HNS_ROCE_HEM_PAGE_SIZE ) { -dev_err (dev,"Just support 4K page size but is 0x%x now!\n" , - mr->umem->page_size); +if (mr->umem->page_shift !=HNS_ROCE_HEM_PAGE_SHIFT ) { +dev_err (dev,"Just support 4K page size but is 0x%lx now!\n" , +BIT (mr->umem->page_shift)); ret = -EINVAL ; goto err_umem; }
drivers/infiniband/hw/hns/hns_roce_qp.c +1 -2
@@ -437,8 +437,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev, } ret =hns_roce_mtt_init (hr_dev,ib_umem_page_count (hr_qp->umem), -ilog2 ((unsigned int )hr_qp->umem->page_size), - &hr_qp->mtt); + hr_qp->umem->page_shift, &hr_qp->mtt);if (ret) {dev_err (dev,"hns_roce_mtt_init error for create qp\n" ); goto err_buf;
drivers/infiniband/hw/i40iw/i40iw_verbs.c +4 -3
@@ -1354,14 +1354,15 @@ static void i40iw_copy_user_pgaddrs(struct i40iw_mr *iwmr, pinfo = (level ==I40IW_LEVEL_1 ) ?NULL : palloc->level2.leaf; - pg_shift =ffs (region->page_size) -1 ; + pg_shift = region->page_shift;for_each_sg (region->sg_head.sgl, sg, region->nmap, entry) { chunk_pages =sg_dma_len (sg) >> pg_shift;if ((iwmr->type ==IW_MEMREG_TYPE_QP ) && !iwpbl->qp_mr.sq_page) iwpbl->qp_mr.sq_page =sg_page (sg);for (i =0 ; i < chunk_pages; i++) { - pg_addr =sg_dma_address (sg) + region->page_size * i; + pg_addr =sg_dma_address (sg) + + (i << region->page_shift);if ((entry + i) ==0 ) *pbl =cpu_to_le64 (pg_addr & iwmr->page_msk);
@@ -1847,7 +1848,7 @@ static struct ib_mr *i40iw_reg_user_mr(struct ib_pd *pd, iwmr->ibmr.device = pd->device; ucontext =to_ucontext (pd->uobject->context); - iwmr->page_size = region->page_size; + iwmr->page_size =PAGE_SIZE ; iwmr->page_msk =PAGE_MASK ;if (region->hugetlb && (req.reg_type ==IW_MEMREG_TYPE_MEM ))
drivers/infiniband/hw/mlx4/cq.c +1 -1
@@ -147,7 +147,7 @@ static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *contreturn PTR_ERR (*umem); err =mlx4_mtt_init (dev->dev,ib_umem_page_count (*umem), -ilog2 ((*umem)->page_size), &buf->mtt); + (*umem)->page_shift, &buf->mtt);if (err) goto err_buf;
drivers/infiniband/hw/mlx4/mr.c +3 -3
@@ -107,7 +107,7 @@ int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, len =sg_dma_len (sg) >> mtt->page_shift;for (k =0 ; k < len; ++k) { pages[i++] =sg_dma_address (sg) + - umem->page_size * k; + (k << umem->page_shift);/* * Be friendly to mlx4_write_mtt() and * pass it chunks of appropriate size.
@@ -155,7 +155,7 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, } n =ib_umem_page_count (mr->umem); - shift =ilog2 (mr->umem->page_size); + shift = mr->umem->page_shift; err =mlx4_mr_alloc (dev->dev,to_mpd (pd)->pdn, virt_addr, length,convert_access (access_flags), n, shift, &mr->mmr);
@@ -239,7 +239,7 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, goto release_mpt_entry; } n =ib_umem_page_count (mmr->umem); - shift =ilog2 (mmr->umem->page_size); + shift = mmr->umem->page_shift; err = mlx4_mr_rereg_mem_write(dev->dev, &mmr->mmr, virt_addr, length, n, shift,
drivers/infiniband/hw/mlx4/qp.c +1 -1
@@ -745,7 +745,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, } err =mlx4_mtt_init (dev->dev,ib_umem_page_count (qp->umem), -ilog2 (qp->umem->page_size), &qp->mtt); + qp->umem->page_shift, &qp->mtt);if (err) goto err_buf;
drivers/infiniband/hw/mlx4/srq.c +1 -1
@@ -122,7 +122,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, } err =mlx4_mtt_init (dev->dev,ib_umem_page_count (srq->umem), -ilog2 (srq->umem->page_size), &srq->mtt); + srq->umem->page_shift, &srq->mtt);if (err) goto err_buf;
drivers/infiniband/hw/mlx5/mem.c +2 -2
@@ -59,7 +59,7 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,u64 pfn;struct scatterlist *sg;int entry; -unsigned long page_shift =ilog2 (umem->page_size); +unsigned long page_shift = umem->page_shift;/* With ODP we must always match OS page size. */ if (umem->odp_data) {
@@ -156,7 +156,7 @@ void __mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem, int page_shift, size_t offset, size_t num_pages, __be64 *pas, int access_flags) { - unsigned long umem_page_shift = ilog2(umem->page_size); + unsigned long umem_page_shift = umem->page_shift;int shift = page_shift - umem_page_shift;int mask = (1 << shift) -1 ;int i, k, idx;
drivers/infiniband/hw/mlx5/odp.c +1 -1
@@ -206,7 +206,7 @@ void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start,* but they will write 0s as well, so no difference in the end result. */ -for (addr = start; addr < end; addr += (u64 )umem->page_size) { +for (addr = start; addr < end; addr +=BIT (umem->page_shift)) { idx = (addr -ib_umem_start (umem)) /PAGE_SIZE ;/* * Strive to write the MTTs in chunks, but avoid overwriting
drivers/infiniband/hw/mthca/mthca_provider.c +2 -3
@@ -937,7 +937,7 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, goto err; } - shift =ffs (mr->umem->page_size) -1 ; + shift = mr->umem->page_shift; n = mr->umem->nmap; mr->mtt =mthca_alloc_mtt (dev, n);
@@ -959,8 +959,7 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,for_each_sg (mr->umem->sg_head.sgl, sg, mr->umem->nmap, entry) { len =sg_dma_len (sg) >> shift;for (k =0 ; k < len; ++k) { - pages[i++] =sg_dma_address (sg) + - mr->umem->page_size * k; + pages[i++] =sg_dma_address (sg) + (k << shift);/* * Be friendly to write_mtt and pass it chunks * of appropriate size.
drivers/infiniband/hw/nes/nes_verbs.c +2 -2
@@ -2165,9 +2165,9 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, }nes_debug (NES_DBG_MR ,"User base = 0x%lX, Virt base = 0x%lX, length = %u," -" offset = %u, page size = %u.\n" , +" offset = %u, page size = %lu.\n" , (unsigned long int )start, (unsigned long int )virt, (u32 )length, -ib_umem_offset (region), region->page_size); +ib_umem_offset (region),BIT (region->page_shift)); skip_pages = ((u32 )ib_umem_offset (region)) >>12 ;
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +6 -9
@@ -914,21 +914,18 @@ static void build_user_pbes(struct ocrdma_dev *dev, struct ocrdma_mr *mr, pbe = (struct ocrdma_pbe *)pbl_tbl->va; pbe_cnt =0 ; - shift =ilog2 (umem->page_size); + shift = umem->page_shift;for_each_sg (umem->sg_head.sgl, sg, umem->nmap, entry) { pages =sg_dma_len (sg) >> shift;for (pg_cnt =0 ; pg_cnt < pages; pg_cnt++) {/* store the page address in pbe */ pbe->pa_lo = -cpu_to_le32 (sg_dma_address - (sg) + - (umem->page_size * pg_cnt)); +cpu_to_le32 (sg_dma_address (sg) + + (pg_cnt << shift)); pbe->pa_hi = -cpu_to_le32 (upper_32_bits - ((sg_dma_address - (sg) + - umem->page_size * pg_cnt))); +cpu_to_le32 (upper_32_bits (sg_dma_address (sg) + + (pg_cnt << shift))); pbe_cnt +=1 ; total_num_pbes +=1 ; pbe++;
@@ -978,7 +975,7 @@ struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,if (status) goto umem_err; - mr->hwmr.pbe_size = mr->umem->page_size; + mr->hwmr.pbe_size =BIT (mr->umem->page_shift); mr->hwmr.fbo =ib_umem_offset (mr->umem); mr->hwmr.va = usr_addr; mr->hwmr.len = len;
drivers/infiniband/hw/qedr/verbs.c +4 -4
@@ -680,16 +680,16 @@ static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem, pbe_cnt =0 ; - shift =ilog2 (umem->page_size); + shift = umem->page_shift;for_each_sg (umem->sg_head.sgl, sg, umem->nmap, entry) { pages =sg_dma_len (sg) >> shift;for (pg_cnt =0 ; pg_cnt < pages; pg_cnt++) {/* store the page address in pbe */ pbe->lo =cpu_to_le32 (sg_dma_address (sg) + - umem->page_size * pg_cnt); + (pg_cnt << shift)); addr =upper_32_bits (sg_dma_address (sg) + - umem->page_size * pg_cnt); + (pg_cnt << shift)); pbe->hi =cpu_to_le32 (addr); pbe_cnt++; total_num_pbes++;
@@ -2189,7 +2189,7 @@ struct ib_mr *qedr_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len, mr->hw_mr.pbl_ptr = mr->info.pbl_table[0 ].pa; mr->hw_mr.pbl_two_level = mr->info.pbl_info.two_layered; mr->hw_mr.pbl_page_size_log =ilog2 (mr->info.pbl_info.pbl_size); - mr->hw_mr.page_size_log =ilog2 (mr->umem->page_size); + mr->hw_mr.page_size_log = mr->umem->page_shift; mr->hw_mr.fbo =ib_umem_offset (mr->umem); mr->hw_mr.length = len; mr->hw_mr.vaddr = usr_addr;
drivers/infiniband/hw/vmw_pvrdma/pvrdma_misc.c +1 -1
@@ -194,7 +194,7 @@ int pvrdma_page_dir_insert_umem(struct pvrdma_page_dir *pdir, len =sg_dma_len (sg) >>PAGE_SHIFT ;for (j =0 ; j < len; j++) {dma_addr_t addr =sg_dma_address (sg) + - umem->page_size * j; + (j << umem->page_shift); ret =pvrdma_page_dir_insert_dma (pdir, i, addr);if (ret)
drivers/infiniband/sw/rdmavt/mr.c +4 -4
@@ -405,8 +405,7 @@ struct ib_mr *rvt_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, mr->mr.access_flags = mr_access_flags; mr->umem = umem; -if (is_power_of_2 (umem->page_size)) - mr->mr.page_shift =ilog2 (umem->page_size); + mr->mr.page_shift = umem->page_shift; m =0 ; n =0 ;for_each_sg (umem->sg_head.sgl, sg, umem->nmap, entry) {
@@ -418,8 +417,9 @@ struct ib_mr *rvt_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, goto bail_inval; } mr->mr.map[m]->segs[n].vaddr = vaddr; - mr->mr.map[m]->segs[n].length = umem->page_size; -trace_rvt_mr_user_seg (&mr->mr, m, n, vaddr, umem->page_size); + mr->mr.map[m]->segs[n].length =BIT (umem->page_shift); +trace_rvt_mr_user_seg (&mr->mr, m, n, vaddr, +BIT (umem->page_shift)); n++;if (n ==RVT_SEGSZ ) { m++;
drivers/infiniband/sw/rxe/rxe_mr.c +3 -5
@@ -191,10 +191,8 @@ int rxe_mem_init_user(struct rxe_dev *rxe, struct rxe_pd *pd, u64 start, goto err1; } -WARN_ON_ONCE (!is_power_of_2 (umem->page_size)); - - mem->page_shift =ilog2 (umem->page_size); - mem->page_mask = umem->page_size -1 ; + mem->page_shift = umem->page_shift; + mem->page_mask =BIT (umem->page_shift) -1 ; num_buf =0 ; map = mem->map;
@@ -210,7 +208,7 @@ int rxe_mem_init_user(struct rxe_dev *rxe, struct rxe_pd *pd, u64 start, } buf->addr = (uintptr_t )vaddr; - buf->size = umem->page_size; + buf->size =BIT (umem->page_shift); num_buf++; buf++;
include/rdma/ib_umem.h +2 -2
@@ -44,7 +44,7 @@ struct ib_umem {struct ib_ucontext *context;size_t length;unsigned long address; -int page_size; +int page_shift;int writable;int hugetlb;struct work_struct work;
@@ -60,7 +60,7 @@ struct ib_umem {/* Returns the offset of the umem start relative to the first page. */ static inline int ib_umem_offset (struct ib_umem *umem) { -return umem->address & ((unsigned long )umem->page_size -1 ); +return umem->address & (BIT (umem->page_shift) -1 ); }/* Returns the first page of an ODP umem. */
--
2.12.0
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20170403100640.3332-2-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
Re: [PATCH rdma-next 01/10] IB: Replace ib_umem page_size by page_shift
Quoted 32 lines · Leon Romanovsky
From: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Size of pages are held by struct
ib_umeminpage_sizefield.It is better to store it as an exponent, because page size by nature is always power-of-two and used as a factor, divisor or ilog2's argument.
The conversion of
page_sizeto bepage_shiftallows to have portable code and avoid following error while compiling on ARM:ERROR: "
__aeabi_uldivmod" [drivers/infiniband/core/ib_core.ko] undefined!CC Selvin Xavier <selvin.xavier-dY08KVG/lbpWk0Htik3J/[email protected]>CC Steve Wise <[email protected]>CC Lijun Ou <[email protected]>CC Shiraz Saleem <[email protected]>CC Adit Ranadive <[email protected]>CC Dennis Dalessandro <[email protected]>CC Ram Amrani <[email protected]>Signed-off-by Leon Romanovsky <[email protected]>---
drivers/infiniband/hw/i40iw/i40iw_verbs.c +1
-1@@ -1354,14 +1354,15 @@ static void i40iw_copy_user_pgaddrs(struct i40iw_mr *iwmr, pinfo = (level ==I40IW_LEVEL_1 ) ?NULL : palloc->level2.leaf; - pg_shift =ffs (region->page_size) -1 ; + pg_shift = region->page_shift;
drivers/infiniband/hw/i40iw/i40iw_verbs.c static void i40iw_copy_user_pgaddrs(struct i40iw_mr *iwmr, · line 1366
Quoted 10 lines
drivers/infiniband/hw/i40iw/i40iw_verbs.c +2
-1for_each_sg (region->sg_head.sgl, sg, region->nmap, entry) { chunk_pages =sg_dma_len (sg) >> pg_shift;if ((iwmr->type ==IW_MEMREG_TYPE_QP ) && !iwpbl->qp_mr.sq_page) iwpbl->qp_mr.sq_page =sg_page (sg);for (i =0 ; i < chunk_pages; i++) { - pg_addr =sg_dma_address (sg) + region->page_size * i; + pg_addr =sg_dma_address (sg) + + (i << region->page_shift);
Remove pg_shift local variable and use region->page_shift directly in this function. --
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20170404225723.GA12652-GOXS9JX10wfOxmVO0tvppfooFf0ArEBIu+b9c/[email protected]
Re: [PATCH rdma-next 01/10] IB: Replace ib_umem page_size by page_shift
Quoted 31 lines · Shiraz Saleem
Quoted 30 lines · Leon Romanovsky
From: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Size of pages are held by struct
ib_umeminpage_sizefield.It is better to store it as an exponent, because page size by nature is always power-of-two and used as a factor, divisor or ilog2's argument.
The conversion of
page_sizeto bepage_shiftallows to have portable code and avoid following error while compiling on ARM:ERROR: "
__aeabi_uldivmod" [drivers/infiniband/core/ib_core.ko] undefined!CC Selvin Xavier <selvin.xavier-dY08KVG/lbpWk0Htik3J/[email protected]>CC Steve Wise <[email protected]>CC Lijun Ou <[email protected]>CC Shiraz Saleem <[email protected]>CC Adit Ranadive <[email protected]>CC Dennis Dalessandro <[email protected]>CC Ram Amrani <[email protected]>Signed-off-by Leon Romanovsky <[email protected]>---
drivers/infiniband/hw/i40iw/i40iw_verbs.c +0
-0@@ -1354,14 +1354,15 @@ static void i40iw_copy_user_pgaddrs(struct i40iw_mr *iwmr, pinfo = (level ==I40IW_LEVEL_1 ) ?NULL : palloc->level2.leaf;
Quoted 14 lines
drivers/infiniband/hw/i40iw/i40iw_verbs.c static void i40iw_copy_user_pgaddrs(struct i40iw_mr *iwmr, · line 1366
Quoted 12 lines
drivers/infiniband/hw/i40iw/i40iw_verbs.c +3
-2- pg_shift =ffs (region->page_size) -1 ; + pg_shift = region->page_shift;for_each_sg (region->sg_head.sgl, sg, region->nmap, entry) { chunk_pages =sg_dma_len (sg) >> pg_shift;if ((iwmr->type ==IW_MEMREG_TYPE_QP ) && !iwpbl->qp_mr.sq_page) iwpbl->qp_mr.sq_page =sg_page (sg);for (i =0 ; i < chunk_pages; i++) { - pg_addr =sg_dma_address (sg) + region->page_size * i; + pg_addr =sg_dma_address (sg) + + (i << region->page_shift);Remove
pg_shiftlocal variable and useregion->page_shiftdirectly in this function.
Sure, I'm sending v1 shortly.
Thanks
Quoted 4 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Steve Wise
Acked-byRE: [PATCH rdma-next 01/10] IB: Replace ib_umem page_size by page_shift
In reply to a message not in the archiveQuoted 23 lines
From: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Size of pages are held by struct
ib_umeminpage_sizefield.It is better to store it as an exponent, because page size by nature is always power-of-two and used as a factor, divisor or ilog2's argument.
The conversion of
page_sizeto bepage_shiftallows to have portable code and avoid following error while compiling on ARM:ERROR: "
__aeabi_uldivmod" [drivers/infiniband/core/ib_core.ko]
undefined!CC Selvin Xavier <selvin.xavier-dY08KVG/lbpWk0Htik3J/[email protected]>CC Steve Wise <[email protected]>CC Lijun Ou <[email protected]>CC Shiraz Saleem <[email protected]>CC Adit Ranadive <[email protected]>CC Dennis Dalessandro <[email protected]>CC Ram Amrani <[email protected]>Signed-off-by Leon Romanovsky <[email protected]>
Quoted 6 lines
--- drivers/infiniband/core/umem.c | 15 ++++++--------- drivers/infiniband/core/umem_odp.c | 12 ++++++------ drivers/infiniband/hw/bnxt_re/ib_verbs.c | 12 ++++++------ drivers/infiniband/hw/cxgb3/iwch_provider.c | 4 ++-- drivers/infiniband/hw/cxgb4/mem.c | 4 ++--
For the cxgb parts:
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/10 IB/mlx5: Fix function updating xlt emergency path
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
In memory shortage path we fall back to use spare buffer. mlx5_ib_update_xlt() called from ib_uverbs_reg_mr when ibmr.ucontext not initialized yet.
Scenario how to test it:
1. trigger memory exhaustion so __get_free_pages(GFP_KERNEL, 4) will fail
2. register MR
3. there should be no kernel oops
--- drivers/infiniband/hw/mlx5/mr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/mr.c +1 -1
@@ -1009,7 +1009,7 @@ int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages, }if (!xlt) { - uctx =to_mucontext (mr->ibmr.uobject->context); + uctx =to_mucontext (mr->ibmr.pd->uobject->context);mlx5_ib_warn (dev,"Using XLT emergency buffer\n" ); size =PAGE_SIZE ; xlt = (void *)uctx->upd_xlt_page;
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 3/10 IB/mlx5: Fix UMR size calculation
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Translation table updates of large UMR may require multiple post send operations. The last operations can be in various lengths, but current code set them to be the same length.
--- drivers/infiniband/hw/mlx5/mr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/mr.c +2 -1
@@ -1045,8 +1045,9 @@ int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,for (pages_mapped =0 ; pages_mapped < pages_to_map && !err; pages_mapped += pages_iter, idx += pages_iter) { + npages =min_t (int, pages_iter, pages_to_map - pages_mapped);dma_sync_single_for_cpu (ddev, dma, size,DMA_TO_DEVICE ); - npages =populate_xlt (mr, idx, pages_iter, xlt, + npages =populate_xlt (mr, idx, npages, xlt, page_shift, size, flags);dma_sync_single_for_device (ddev, dma, size,DMA_TO_DEVICE );
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 4/10 IB/mlx5: Fix implicit MR GC
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
When implicit MR's leaf MKey becomes unused, i.e. when it's last page being released my MMU invalidation it is marked as "dying" and scheduled for release by garbage collector.
Currentle consequent page fault may remove "dying" flag. Treat leaf MKey as non-existent once it was scheduled to removal by GC.
--- drivers/infiniband/hw/mlx5/odp.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
drivers/infiniband/hw/mlx5/odp.c +1 -10
@@ -57,7 +57,7 @@ static int check_parent(struct ib_umem_odp *odp, {struct mlx5_ib_mr *mr = odp->private; -return mr && mr->parent == parent; +return mr && mr->parent == parent && !odp->dying; }static struct ib_umem_odp *odp_next (struct ib_umem_odp *odp)
@@ -158,13 +158,6 @@ static void mr_leaf_free_action(struct work_struct *work) mr->parent =NULL ;synchronize_srcu (&mr->dev->mr_srcu); -if (!READ_ONCE (odp->dying)) { - mr->parent = imr; -if (atomic_dec_and_test (&imr->num_leaf_free)) -wake_up (&imr->q_leaf_free); -return ; - } -ib_umem_release (odp->umem);if (imr->live) mlx5_ib_update_xlt(imr, idx, 1, 0,
@@ -436,8 +429,6 @@ static struct ib_umem_odp *implicit_mr_get_data(struct mlx5_ib_mr *mr, nentries++; } - odp->dying =0 ; -/* Return first odp if region not covered by single one */ if (likely (!result)) result = odp;
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 5/10 IB/mlx5: Decrease verbosity level of ODP errors
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Decrease verbosity level of ODP error flows messages to debug level. Remove one redundant print since debug level message already exists in this flow.
--- drivers/infiniband/hw/mlx5/odp.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
drivers/infiniband/hw/mlx5/odp.c +4 -7
@@ -988,9 +988,6 @@ static void mlx5_ib_mr_wqe_pfault_handler(struct mlx5_ib_dev *dev, resume_with_error =0 ; goto resolve_page_fault; }else if (ret <0 || total_wqe_bytes > bytes_mapped) { -if (ret != -ENOENT ) -mlx5_ib_err (dev,"PAGE FAULT error: %d. QP 0x%x. type: 0x%x\n" , - ret, pfault->wqe.wq_num, pfault->type); goto resolve_page_fault; }
@@ -1050,8 +1047,8 @@ static void mlx5_ib_mr_rdma_pfault_handler(struct mlx5_ib_dev *dev, }else if (ret <0 ||pages_in_range (address, length) > ret) {mlx5_ib_page_fault_resume (dev, pfault,1 );if (ret != -ENOENT ) -mlx5_ib_warn (dev,"PAGE FAULT error %d. QP 0x%x, type: 0x%x\n" , - ret, pfault->token, pfault->type); +mlx5_ib_dbg (dev,"PAGE FAULT error %d. QP 0x%x, type: 0x%x\n" , + ret, pfault->token, pfault->type);return ; }
@@ -1072,8 +1069,8 @@ static void mlx5_ib_mr_rdma_pfault_handler(struct mlx5_ib_dev *dev, prefetch_len, &bytes_committed, NULL);if (ret <0 && ret != -EAGAIN ) { -mlx5_ib_warn (dev,"Prefetch failed. ret: %d, QP 0x%x, address: 0x%.16llx, length = 0x%.16x\n" , - ret, pfault->token, address, prefetch_len); +mlx5_ib_dbg (dev,"Prefetch failed. ret: %d, QP 0x%x, address: 0x%.16llx, length = 0x%.16x\n" , + ret, pfault->token, address, prefetch_len); } } }
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 6/10 IB/umem: Add contiguous ODP support
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Currenlty ODP supports only regular MMU pages.
Add ODP support for regions consisting of physically contiguous chunks of arbitrary order (huge pages for instance) to improve performance.
--- drivers/infiniband/core/umem_odp.c | 50 +++++++++++++++++++++++--------------- include/rdma/ib_umem.h | 4 +-- 2 files changed, 33 insertions(+), 21 deletions(-)
drivers/infiniband/core/umem_odp.c +31 -19
@@ -504,7 +504,6 @@ void ib_umem_odp_release(struct ib_umem *umem)static int ib_umem_odp_map_dma_single_page (struct ib_umem *umem,int page_index, -u64 base_virt_addr,struct page *page,u64 access_mask,unsigned long current_seq)
@@ -527,7 +526,7 @@ static int ib_umem_odp_map_dma_single_page(if (!(umem->odp_data->dma_list[page_index])) { dma_addr =ib_dma_map_page (dev, page, -0 ,PAGE_SIZE , +0 ,BIT (umem->page_shift),DMA_BIDIRECTIONAL );if (ib_dma_mapping_error (dev, dma_addr)) { ret = -EFAULT ;
@@ -555,8 +554,9 @@ static int ib_umem_odp_map_dma_single_page(if (remove_existing_mapping && umem->context->invalidate_range) {invalidate_page_trampoline ( umem, - base_virt_addr + (page_index *PAGE_SIZE ), - base_virt_addr + ((page_index+1 )*PAGE_SIZE ), +ib_umem_start (umem) + (page_index >> umem->page_shift), +ib_umem_start (umem) + ((page_index +1 ) >> + umem->page_shift),NULL ); ret = -EAGAIN ; }
@@ -595,10 +595,10 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,struct task_struct *owning_process =NULL ;struct mm_struct *owning_mm =NULL ;struct page **local_page_list =NULL ; -u64 off; -int j, k, ret =0 , start_idx, npages =0 ; -u64 base_virt_addr; +u64 page_mask, off; +int j, k, ret =0 , start_idx, npages =0 , page_shift;unsigned int flags =0 ; +phys_addr_t p =0 ;if (access_mask ==0 )return -EINVAL ;
@@ -611,9 +611,10 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,if (!local_page_list)return -ENOMEM ; - off = user_virt & (~PAGE_MASK ); - user_virt = user_virt &PAGE_MASK ; - base_virt_addr = user_virt; + page_shift = umem->page_shift; + page_mask = ~(BIT (page_shift) -1 ); + off = user_virt & (~page_mask); + user_virt = user_virt & page_mask; bcnt += off;/* Charge for the first page offset as well. */ owning_process =get_pid_task (umem->context->tgid,PIDTYPE_PID );
@@ -631,13 +632,13 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,if (access_mask &ODP_WRITE_ALLOWED_BIT ) flags |=FOLL_WRITE ; - start_idx = (user_virt -ib_umem_start (umem)) >>PAGE_SHIFT ; + start_idx = (user_virt -ib_umem_start (umem)) >> page_shift; k = start_idx;while (bcnt >0 ) { -const size_t gup_num_pages = -min_t (size_t,ALIGN (bcnt,PAGE_SIZE ) /PAGE_SIZE , -PAGE_SIZE /sizeof (struct page *)); +const size_t gup_num_pages =min_t (size_t, + (bcnt +BIT (page_shift) -1 ) >> page_shift, +PAGE_SIZE /sizeof (struct page *));down_read (&owning_mm->mmap_sem);/*
@@ -656,14 +657,25 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,break ; bcnt -=min_t (size_t, npages <<PAGE_SHIFT , bcnt); - user_virt += npages <<PAGE_SHIFT ;mutex_lock (&umem->odp_data->umem_mutex); -for (j =0 ; j < npages; ++j) { +for (j =0 ; j < npages; j++, user_virt +=PAGE_SIZE ) { +if (user_virt & ~page_mask) { + p +=PAGE_SIZE ; +if (page_to_phys (local_page_list[j]) != p) { + ret = -EFAULT ; +break ; + } +put_page (local_page_list[j]); +continue ; + } + ret =ib_umem_odp_map_dma_single_page ( - umem, k, base_virt_addr, local_page_list[j], - access_mask, current_seq); + umem, k, local_page_list[j], + access_mask, current_seq);if (ret <0 )break ; + + p =page_to_phys (local_page_list[j]); k++; }mutex_unlock (&umem->odp_data->umem_mutex);
@@ -708,7 +720,7 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem *umem, u64 virt,* once. */ mutex_lock (&umem->odp_data->umem_mutex);for (addr = virt; addr < bound; addr +=BIT (umem->page_shift)) { - idx = (addr -ib_umem_start (umem)) /PAGE_SIZE ; + idx = (addr -ib_umem_start (umem)) >> umem->page_shift;if (umem->odp_data->page_list[idx]) {struct page *page = umem->odp_data->page_list[idx];dma_addr_t dma = umem->odp_data->dma_list[idx];
include/rdma/ib_umem.h +2 -2
@@ -72,12 +72,12 @@ static inline unsigned long ib_umem_start(struct ib_umem *umem)/* Returns the address of the page after the last one of an ODP umem. */ static inline unsigned long ib_umem_end (struct ib_umem *umem) { -return PAGE_ALIGN (umem->address + umem->length); +return ALIGN (umem->address + umem->length,BIT (umem->page_shift)); }static inline size_t ib_umem_num_pages (struct ib_umem *umem) { -return (ib_umem_end (umem) -ib_umem_start (umem)) >>PAGE_SHIFT ; +return (ib_umem_end (umem) -ib_umem_start (umem)) >> umem->page_shift; }#ifdef CONFIG_INFINIBAND_USER_MEM
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 7/10 IB/mlx5: Add contiguous ODP support
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Currenlty ODP supports only regular MMU pages.
Add ODP support for regions consisting of physically contiguous chunks of arbitrary order (huge pages for instance) to improve performance.
--- drivers/infiniband/hw/mlx5/mem.c | 9 ++++----- drivers/infiniband/hw/mlx5/odp.c | 28 +++++++++++++++------------- 2 files changed, 19 insertions(+), 18 deletions(-)
drivers/infiniband/hw/mlx5/mem.c +4 -5
@@ -61,13 +61,12 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,int entry;unsigned long page_shift = umem->page_shift; -/* With ODP we must always match OS page size. */ if (umem->odp_data) { - *count =ib_umem_page_count (umem); - *shift =PAGE_SHIFT ; - *ncont = *count; + *ncont =ib_umem_page_count (umem); + *count = *ncont << (page_shift -PAGE_SHIFT ); + *shift = page_shift;if (order) - *order =ilog2 (roundup_pow_of_two (*count)); + *order =ilog2 (roundup_pow_of_two (*ncont));return ; }
drivers/infiniband/hw/mlx5/odp.c +15 -13
@@ -200,7 +200,7 @@ void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start,*/ for (addr = start; addr < end; addr +=BIT (umem->page_shift)) { - idx = (addr -ib_umem_start (umem)) /PAGE_SIZE ; + idx = (addr -ib_umem_start (umem)) >> umem->page_shift;/* * Strive to write the MTTs in chunks, but avoid overwriting * non-existing MTTs. The huristic here can be improved to
@@ -218,8 +218,7 @@ void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start,if (in_block && umr_offset ==0 ) {mlx5_ib_update_xlt (mr, blk_start_idx, - idx - blk_start_idx, -PAGE_SHIFT , + idx - blk_start_idx,0 ,MLX5_IB_UPD_XLT_ZAP |MLX5_IB_UPD_XLT_ATOMIC ); in_block =0 ;
@@ -228,8 +227,7 @@ void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start, }if (in_block)mlx5_ib_update_xlt (mr, blk_start_idx, - idx - blk_start_idx +1 , -PAGE_SHIFT , + idx - blk_start_idx +1 ,0 ,MLX5_IB_UPD_XLT_ZAP |MLX5_IB_UPD_XLT_ATOMIC );/*
@@ -516,7 +514,7 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)/* * Handle a single data segment in a page-fault WQE or RDMA region. * -* Returns number of pages retrieved on success. The caller may continue to +* Returns number of OS pages retrieved on success. The caller may continue to * the next data segment. * Can return the following error codes: * -EAGAIN to designate a temporary error. The caller will abort handling the
@@ -531,13 +529,14 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev, {int srcu_key;unsigned int current_seq =0 ; -u64 start_idx; +u64 start_idx, page_mask;int npages =0 , ret =0 ;struct mlx5_ib_mr *mr;u64 access_mask =ODP_READ_ALLOWED_BIT ;struct ib_umem_odp *odp;int implicit =0 ;size_t size; +int page_shift; srcu_key =srcu_read_lock (&dev->mr_srcu); mr =mlx5_ib_odp_find_mr_lkey (dev, key);
@@ -583,6 +582,9 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev, odp = mr->umem->odp_data; } + page_shift = mr->umem->page_shift; + page_mask = ~(BIT (page_shift) -1 ); + next_mr: current_seq =READ_ONCE (odp->notifiers_seq);/*
@@ -592,7 +594,7 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,smp_rmb (); size =min_t (size_t, bcnt,ib_umem_end (odp->umem) - io_virt); - start_idx = (io_virt - (mr->mmkey.iova &PAGE_MASK )) >>PAGE_SHIFT ; + start_idx = (io_virt - (mr->mmkey.iova & page_mask)) >> page_shift;if (mr->umem->writable) access_mask |=ODP_WRITE_ALLOWED_BIT ;
@@ -614,7 +616,7 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,* checks this. */ ret =mlx5_ib_update_xlt (mr, start_idx, np, -PAGE_SHIFT , + page_shift,MLX5_IB_UPD_XLT_ATOMIC ); }else { ret = -EAGAIN ;
@@ -625,14 +627,14 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,mlx5_ib_err (dev,"Failed to update mkey page tables\n" ); goto srcu_unlock; } -if (bytes_mapped) { -u32 new_mappings = np *PAGE_SIZE - - (io_virt -round_down (io_virt,PAGE_SIZE )); +u32 new_mappings = (np << page_shift) - + (io_virt -round_down (io_virt, +1 << page_shift)); *bytes_mapped +=min_t (u32, new_mappings, size); } - npages += np; + npages += np << (page_shift -PAGE_SHIFT ); } bcnt -= size;
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 8/10 IB/umem: Add support to huge ODP
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Add IB_ACCESS_HUGETLB ib_reg_mr flag.
Hugetlb region registered with this flag
will use single translation entry per huge page.
--- drivers/infiniband/core/umem.c | 2 +- drivers/infiniband/core/umem_odp.c | 19 +++++++++++++++++-- include/rdma/ib_umem_odp.h | 6 ++++-- include/rdma/ib_verbs.h | 1 + 4 files changed, 23 insertions(+), 5 deletions(-)
drivers/infiniband/core/umem.c +1 -1
@@ -133,7 +133,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,if (access &IB_ACCESS_ON_DEMAND ) {put_pid (umem->pid); - ret =ib_umem_odp_get (context, umem); + ret =ib_umem_odp_get (context, umem, access);if (ret) {kfree (umem);return ERR_PTR (ret);
drivers/infiniband/core/umem_odp.c +17 -2
@@ -38,6 +38,7 @@#include <linux/slab.h> #include <linux/export.h> #include <linux/vmalloc.h> +#include <linux/hugetlb.h> #include <rdma/ib_verbs.h> #include <rdma/ib_umem.h>
@@ -306,7 +307,8 @@ struct ib_umem *ib_alloc_odp_umem(struct ib_ucontext *context, }EXPORT_SYMBOL (ib_alloc_odp_umem); -int ib_umem_odp_get (struct ib_ucontext *context,struct ib_umem *umem) +int ib_umem_odp_get (struct ib_ucontext *context,struct ib_umem *umem, +int access) {int ret_val;struct pid *our_pid;
@@ -315,6 +317,20 @@ int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem)if (!mm)return -EINVAL ; +if (access &IB_ACCESS_HUGETLB ) { +struct vm_area_struct *vma; +struct hstate *h; + + vma =find_vma (mm,ib_umem_start (umem)); +if (!vma || !is_vm_hugetlb_page (vma)) +return -EINVAL ; + h =hstate_vma (vma); + umem->page_shift =huge_page_shift (h); + umem->hugetlb =1 ; + }else { + umem->hugetlb =0 ; + } +/* Prevent creating ODP MRs in child processes */ rcu_read_lock (); our_pid =get_task_pid (current->group_leader,PIDTYPE_PID );
@@ -325,7 +341,6 @@ int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem) goto out_mm; } - umem->hugetlb =0 ; umem->odp_data =kzalloc (sizeof (*umem->odp_data),GFP_KERNEL );if (!umem->odp_data) { ret_val = -ENOMEM ;
include/rdma/ib_umem_odp.h +4 -2
@@ -84,7 +84,8 @@ struct ib_umem_odp {#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING -int ib_umem_odp_get (struct ib_ucontext *context,struct ib_umem *umem); +int ib_umem_odp_get (struct ib_ucontext *context,struct ib_umem *umem, +int access);struct ib_umem *ib_alloc_odp_umem (struct ib_ucontext *context,unsigned long addr,size_t size);
@@ -154,7 +155,8 @@ static inline int ib_umem_mmu_notifier_retry(struct ib_umem *item,#else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ static inline int ib_umem_odp_get (struct ib_ucontext *context, -struct ib_umem *umem) +struct ib_umem *umem, +int access) {return -EINVAL ; }
include/rdma/ib_verbs.h +1 -0
@@ -1336,6 +1336,7 @@ enum ib_access_flags {IB_ACCESS_MW_BIND = (1 <<4 ),IB_ZERO_BASED = (1 <<5 ),IB_ACCESS_ON_DEMAND = (1 <<6 ), + IB_ACCESS_HUGETLB = (1<<7), };/*
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 9/10 IB/mlx5: Extract page fault code
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
To make page fault handling code more flexible split pagefault_single_data_segment() function. Keep MR resolution in pagefault_single_data_segment() and move actual updates into pagefault_single_mr().
--- drivers/infiniband/hw/mlx5/odp.c | 203 ++++++++++++++++++++------------------- 1 file changed, 104 insertions(+), 99 deletions(-)
drivers/infiniband/hw/mlx5/odp.c +104 -99
@@ -511,81 +511,38 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)wait_event (imr->q_leaf_free, !atomic_read (&imr->num_leaf_free)); } -/* -* Handle a single data segment in a page-fault WQE or RDMA region. -* -* Returns number of OS pages retrieved on success. The caller may continue to -* the next data segment. -* Can return the following error codes: -* -EAGAIN to designate a temporary error. The caller will abort handling the -* page fault and resolve it. -* -EFAULT when there's an error mapping the requested pages. The caller will -* abort the page fault handling. -*/ -static int pagefault_single_data_segment (struct mlx5_ib_dev *dev, -u32 key,u64 io_virt,size_t bcnt, -u32 *bytes_committed, -u32 *bytes_mapped) +static int pagefault_mr (struct mlx5_ib_dev *dev,struct mlx5_ib_mr *mr, +u64 io_virt,size_t bcnt,u32 *bytes_mapped) { -int srcu_key; -unsigned int current_seq =0 ; -u64 start_idx, page_mask; -int npages =0 , ret =0 ; -struct mlx5_ib_mr *mr;u64 access_mask =ODP_READ_ALLOWED_BIT ; +int npages =0 , page_shift, np; +u64 start_idx, page_mask;struct ib_umem_odp *odp; -int implicit =0 ; +int current_seq;size_t size; -int page_shift; - - srcu_key =srcu_read_lock (&dev->mr_srcu); - mr =mlx5_ib_odp_find_mr_lkey (dev, key); -/* -* If we didn't find the MR, it means the MR was closed while we were -* handling the ODP event. In this case we return -EFAULT so that the -* QP will be closed. -*/ -if (!mr || !mr->ibmr.pd) { -mlx5_ib_dbg (dev,"Failed to find relevant mr for lkey=0x%06x, probably the MR was destroyed\n" , - key); - ret = -EFAULT ; - goto srcu_unlock; - } -if (!mr->umem->odp_data) { -mlx5_ib_dbg (dev,"skipping non ODP MR (lkey=0x%06x) in page fault handler.\n" , - key); -if (bytes_mapped) - *bytes_mapped += - (bcnt - *bytes_committed); - goto srcu_unlock; - } - -/* -* Avoid branches - this code will perform correctly -* in all iterations (in iteration 2 and above, -* bytes_committed == 0). -*/ - io_virt += *bytes_committed; - bcnt -= *bytes_committed; +int ret;if (!mr->umem->odp_data->page_list) { odp =implicit_mr_get_data (mr, io_virt, bcnt); -if (IS_ERR (odp)) { - ret =PTR_ERR (odp); - goto srcu_unlock; - } +if (IS_ERR (odp)) +return PTR_ERR (odp); mr = odp->private; - implicit =1 ; }else { odp = mr->umem->odp_data; } +next_mr: + size =min_t (size_t, bcnt,ib_umem_end (odp->umem) - io_virt); + page_shift = mr->umem->page_shift; page_mask = ~(BIT (page_shift) -1 ); + start_idx = (io_virt - (mr->mmkey.iova & page_mask)) >> page_shift; + +if (mr->umem->writable) + access_mask |=ODP_WRITE_ALLOWED_BIT ; -next_mr: current_seq =READ_ONCE (odp->notifiers_seq);/* * Ensure the sequence number is valid for some time before we call
@@ -593,51 +550,43 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,*/ smp_rmb (); - size =min_t (size_t, bcnt,ib_umem_end (odp->umem) - io_virt); - start_idx = (io_virt - (mr->mmkey.iova & page_mask)) >> page_shift; - -if (mr->umem->writable) - access_mask |=ODP_WRITE_ALLOWED_BIT ; - ret =ib_umem_odp_map_dma_pages (mr->umem, io_virt, size, access_mask, current_seq);if (ret <0 ) - goto srcu_unlock; + goto out; -if (ret >0 ) { -int np = ret; - -mutex_lock (&odp->umem_mutex); -if (!ib_umem_mmu_notifier_retry (mr->umem, current_seq)) { -/* -* No need to check whether the MTTs really belong to -* this MR, since ib_umem_odp_map_dma_pages already -* checks this. -*/ - ret =mlx5_ib_update_xlt (mr, start_idx, np, - page_shift, -MLX5_IB_UPD_XLT_ATOMIC ); - }else { - ret = -EAGAIN ; - } -mutex_unlock (&odp->umem_mutex); -if (ret <0 ) { -if (ret != -EAGAIN ) -mlx5_ib_err (dev,"Failed to update mkey page tables\n" ); - goto srcu_unlock; - } -if (bytes_mapped) { -u32 new_mappings = (np << page_shift) - - (io_virt -round_down (io_virt, -1 << page_shift)); - *bytes_mapped +=min_t (u32, new_mappings, size); - } + np = ret; - npages += np << (page_shift -PAGE_SHIFT ); +mutex_lock (&odp->umem_mutex); +if (!ib_umem_mmu_notifier_retry (mr->umem, current_seq)) { +/* +* No need to check whether the MTTs really belong to +* this MR, since ib_umem_odp_map_dma_pages already +* checks this. +*/ + ret =mlx5_ib_update_xlt (mr, start_idx, np, + page_shift,MLX5_IB_UPD_XLT_ATOMIC ); + }else { + ret = -EAGAIN ; } +mutex_unlock (&odp->umem_mutex); +if (ret <0 ) { +if (ret != -EAGAIN ) +mlx5_ib_err (dev,"Failed to update mkey page tables\n" ); + goto out; + } + +if (bytes_mapped) { +u32 new_mappings = (np << page_shift) - + (io_virt -round_down (io_virt,1 << page_shift)); + *bytes_mapped +=min_t (u32, new_mappings, size); + } + + npages += np << (page_shift -PAGE_SHIFT ); bcnt -= size; +if (unlikely (bcnt)) {struct ib_umem_odp *next;
@@ -646,17 +595,18 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,if (unlikely (!next || next->umem->address != io_virt)) {mlx5_ib_dbg (dev,"next implicit leaf removed at 0x%llx. got %p\n" , io_virt, next); - ret = -EAGAIN ; - goto srcu_unlock_no_wait; +return -EAGAIN ; } odp = next; mr = odp->private; goto next_mr; } -srcu_unlock: +return npages; + +out:if (ret == -EAGAIN ) { -if (implicit || !odp->dying) { +if (mr->parent || !odp->dying) {unsigned long timeout =msecs_to_jiffies (MMU_NOTIFIER_TIMEOUT );
@@ -672,7 +622,62 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev, } } -srcu_unlock_no_wait: +return ret; +} + +/* +* Handle a single data segment in a page-fault WQE or RDMA region. +* +* Returns number of OS pages retrieved on success. The caller may continue to +* the next data segment. +* Can return the following error codes: +* -EAGAIN to designate a temporary error. The caller will abort handling the +* page fault and resolve it. +* -EFAULT when there's an error mapping the requested pages. The caller will +* abort the page fault handling. +*/ +static int pagefault_single_data_segment (struct mlx5_ib_dev *dev, +u32 key,u64 io_virt,size_t bcnt, +u32 *bytes_committed, +u32 *bytes_mapped) +{ +int npages =0 , srcu_key, ret; +struct mlx5_ib_mr *mr; +size_t size; + + srcu_key =srcu_read_lock (&dev->mr_srcu); + mr =mlx5_ib_odp_find_mr_lkey (dev, key); +/* +* If we didn't find the MR, it means the MR was closed while we were +* handling the ODP event. In this case we return -EFAULT so that the +* QP will be closed. +*/ +if (!mr || !mr->ibmr.pd) { +mlx5_ib_dbg (dev,"Failed to find relevant mr for lkey=0x%06x, probably the MR was destroyed\n" , + key); + ret = -EFAULT ; + goto srcu_unlock; + } +if (!mr->umem->odp_data) { +mlx5_ib_dbg (dev,"skipping non ODP MR (lkey=0x%06x) in page fault handler.\n" , + key); +if (bytes_mapped) + *bytes_mapped += + (bcnt - *bytes_committed); + goto srcu_unlock; + } + +/* +* Avoid branches - this code will perform correctly +* in all iterations (in iteration 2 and above, +* bytes_committed == 0). +*/ + io_virt += *bytes_committed; + bcnt -= *bytes_committed; + + npages =pagefault_mr (dev, mr, io_virt, size, bytes_mapped); + +srcu_unlock:srcu_read_unlock (&dev->mr_srcu, srcu_key); *bytes_committed =0 ;return ret ? ret : npages;
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 10/10 IB/mlx5: Add ODP support to MW
In reply to a message not in the archiveFrom: Artemy Kovalyov <artemyko-VPRAkNaXOzVWk0Htik3J/[email protected]>
Internally MW implemented as KLM MKey and filled by userspace UMR postsends. Handle pagefault trigered by operations on this MKeys.
--- drivers/infiniband/hw/mlx5/mlx5_ib.h | 1 + drivers/infiniband/hw/mlx5/mr.c | 1 + drivers/infiniband/hw/mlx5/odp.c | 161 +++++++++++++++++++++++++---------- 3 files changed, 120 insertions(+), 43 deletions(-)
drivers/infiniband/hw/mlx5/mlx5_ib.h +1 -0
@@ -513,6 +513,7 @@ struct mlx5_ib_mr {struct mlx5_ib_mw {struct ib_mw ibmw;struct mlx5_core_mkey mmkey; +int ndescs; };struct mlx5_ib_umr_context {
drivers/infiniband/hw/mlx5/mr.c +1 -0
@@ -1688,6 +1688,7 @@ struct ib_mw *mlx5_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type, mw->mmkey.type =MLX5_MKEY_MW ; mw->ibmw.rkey = mw->mmkey.key; + mw->ndescs = ndescs; resp.response_length =min (offsetof(typeof (resp ), response_length) +sizeof (resp.response_length), udata->outlen);
drivers/infiniband/hw/mlx5/odp.c +118 -43
191 lines not on this page · raw message
Signature · 6 lines
2.12.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html