Skip to content

Commit 235f238

Browse files
gurmichaelrleon
authored andcommitted
RDMA/mlx5: Fix indirect mkey ODP page count
Restrict the check for the number of pages handled during an ODP page fault to direct mkeys. Perform the check right after handling the page fault and don't propagate the number of handled pages to callers. Indirect mkeys and their associated direct mkeys can have different start addresses. As a result, the calculation of the number of pages to handle for an indirect mkey may not match the actual page fault handling done on the direct mkey. For example: A 4K sized page fault on a KSM mkey that has a start address that is not aligned to a page will result a calculation that assumes the number of pages required to handle are 2. While the underlying MTT might be aligned will require fetching only a single page. Thus, do the calculation and compare number of pages handled only per direct mkey. Fixes: db570d7 ("IB/mlx5: Add ODP support to MW") Signed-off-by: Michael Guralnik <michaelgur@nvidia.com> Reviewed-by: Artemy Kovalyov <artemyko@nvidia.com> Link: https://patch.msgid.link/86c483d9e75ce8fe14e9ff85b62df72b779f8ab1.1736187990.git.leon@kernel.org Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent 76b2691 commit 235f238

1 file changed

Lines changed: 15 additions & 17 deletions

File tree

  • drivers/infiniband/hw/mlx5

drivers/infiniband/hw/mlx5/odp.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -944,8 +944,7 @@ static struct mlx5_ib_mkey *find_odp_mkey(struct mlx5_ib_dev *dev, u32 key)
944944
/*
945945
* Handle a single data segment in a page-fault WQE or RDMA region.
946946
*
947-
* Returns number of OS pages retrieved on success. The caller may continue to
948-
* the next data segment.
947+
* Returns zero on success. The caller may continue to the next data segment.
949948
* Can return the following error codes:
950949
* -EAGAIN to designate a temporary error. The caller will abort handling the
951950
* page fault and resolve it.
@@ -958,7 +957,7 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
958957
u32 *bytes_committed,
959958
u32 *bytes_mapped)
960959
{
961-
int npages = 0, ret, i, outlen, cur_outlen = 0, depth = 0;
960+
int ret, i, outlen, cur_outlen = 0, depth = 0, pages_in_range;
962961
struct pf_frame *head = NULL, *frame;
963962
struct mlx5_ib_mkey *mmkey;
964963
struct mlx5_ib_mr *mr;
@@ -993,13 +992,20 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
993992
case MLX5_MKEY_MR:
994993
mr = container_of(mmkey, struct mlx5_ib_mr, mmkey);
995994

995+
pages_in_range = (ALIGN(io_virt + bcnt, PAGE_SIZE) -
996+
(io_virt & PAGE_MASK)) >>
997+
PAGE_SHIFT;
996998
ret = pagefault_mr(mr, io_virt, bcnt, bytes_mapped, 0, false);
997999
if (ret < 0)
9981000
goto end;
9991001

10001002
mlx5_update_odp_stats_with_handled(mr, faults, ret);
10011003

1002-
npages += ret;
1004+
if (ret < pages_in_range) {
1005+
ret = -EFAULT;
1006+
goto end;
1007+
}
1008+
10031009
ret = 0;
10041010
break;
10051011

@@ -1090,7 +1096,7 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
10901096
kfree(out);
10911097

10921098
*bytes_committed = 0;
1093-
return ret ? ret : npages;
1099+
return ret;
10941100
}
10951101

10961102
/*
@@ -1109,16 +1115,15 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
11091115
* the committed bytes).
11101116
* @receive_queue: receive WQE end of sg list
11111117
*
1112-
* Returns the number of pages loaded if positive, zero for an empty WQE, or a
1113-
* negative error code.
1118+
* Returns zero for success or a negative error code.
11141119
*/
11151120
static int pagefault_data_segments(struct mlx5_ib_dev *dev,
11161121
struct mlx5_pagefault *pfault,
11171122
void *wqe,
11181123
void *wqe_end, u32 *bytes_mapped,
11191124
u32 *total_wqe_bytes, bool receive_queue)
11201125
{
1121-
int ret = 0, npages = 0;
1126+
int ret = 0;
11221127
u64 io_virt;
11231128
__be32 key;
11241129
u32 byte_count;
@@ -1175,10 +1180,9 @@ static int pagefault_data_segments(struct mlx5_ib_dev *dev,
11751180
bytes_mapped);
11761181
if (ret < 0)
11771182
break;
1178-
npages += ret;
11791183
}
11801184

1181-
return ret < 0 ? ret : npages;
1185+
return ret;
11821186
}
11831187

11841188
/*
@@ -1414,12 +1418,6 @@ static void mlx5_ib_mr_wqe_pfault_handler(struct mlx5_ib_dev *dev,
14141418
free_page((unsigned long)wqe_start);
14151419
}
14161420

1417-
static int pages_in_range(u64 address, u32 length)
1418-
{
1419-
return (ALIGN(address + length, PAGE_SIZE) -
1420-
(address & PAGE_MASK)) >> PAGE_SHIFT;
1421-
}
1422-
14231421
static void mlx5_ib_mr_rdma_pfault_handler(struct mlx5_ib_dev *dev,
14241422
struct mlx5_pagefault *pfault)
14251423
{
@@ -1458,7 +1456,7 @@ static void mlx5_ib_mr_rdma_pfault_handler(struct mlx5_ib_dev *dev,
14581456
if (ret == -EAGAIN) {
14591457
/* We're racing with an invalidation, don't prefetch */
14601458
prefetch_activated = 0;
1461-
} else if (ret < 0 || pages_in_range(address, length) > ret) {
1459+
} else if (ret < 0) {
14621460
mlx5_ib_page_fault_resume(dev, pfault, 1);
14631461
if (ret != -ENOENT)
14641462
mlx5_ib_dbg(dev, "PAGE FAULT error %d. QP 0x%llx, type: 0x%x\n",

0 commit comments

Comments
 (0)