diff options
Diffstat (limited to 'drivers/infiniband/hw/mlx5/mem.c')
-rw-r--r-- | drivers/infiniband/hw/mlx5/mem.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mlx5/mem.c b/drivers/infiniband/hw/mlx5/mem.c index 19354b6c8153..0d74eacce922 100644 --- a/drivers/infiniband/hw/mlx5/mem.c +++ b/drivers/infiniband/hw/mlx5/mem.c @@ -154,6 +154,8 @@ void __mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem, __be64 *pas, int access_flags, void *data) { unsigned long umem_page_shift = ilog2(umem->page_size); + unsigned long start = ib_umem_start(umem) + (offset << PAGE_SHIFT); + unsigned long end = start + (num_pages << PAGE_SHIFT); int shift = page_shift - umem_page_shift; int mask = (1 << shift) - 1; int i, k; @@ -164,6 +166,42 @@ void __mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem, int entry; #if IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING) #if IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING_HMM) + if (umem->odp_data) { + struct ib_mirror *ib_mirror = umem->odp_data->ib_mirror; + struct hmm_mirror *mirror = &ib_mirror->base; + struct hmm_pt_iter *iter = data, local_iter; + unsigned long addr; + + if (iter == NULL) { + iter = &local_iter; + hmm_pt_iter_init(iter, &mirror->pt); + } + + for (i=0, addr=start; i < num_pages; ++i, addr+=PAGE_SIZE) { + unsigned long next = end; + dma_addr_t *ptep, pte; + + /* Get and lock pointer to mirror page table. */ + ptep = hmm_pt_iter_lookup(iter, addr, &next); + pte = ptep ? *ptep : 0; + /* + * HMM will not have any page tables set up, if this + * function is called before page faults have happened + * on the MR. In that case, we don't have PA's yet, so + * just set each one to zero and continue on. The hw + * will trigger a page fault. + */ + if (hmm_pte_test_valid_dma(&pte)) + pas[i] = cpu_to_be64(umem_dma_to_mtt(pte)); + else + pas[i] = (__be64)0; + } + + if (iter == &local_iter) + hmm_pt_iter_fini(iter); + + return; + } #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING_HMM */ const bool odp = umem->odp_data != NULL; |