Skip to content

Commit 33e3960

Browse files
rouminggregkh
authored andcommitted
RDMA/rtrs-srv: fix SG mapping
[ Upstream commit 83835f7 ] This fixes the following error on the server side: RTRS server session allocation failed: -EINVAL caused by the caller of the `ib_dma_map_sg()`, which does not expect less mapped entries, than requested, which is in the order of things and can be easily reproduced on the machine with enabled IOMMU. The fix is to treat any positive number of mapped sg entries as a successful mapping and cache DMA addresses by traversing modified SG table. Fixes: 9cb8374 ("RDMA/rtrs: server: main functionality") Signed-off-by: Roman Penyaev <r.peniaev@gmail.com> Signed-off-by: Jack Wang <jinpu.wang@ionos.com> Signed-off-by: Grzegorz Prajsner <grzegorz.prajsner@ionos.com> Link: https://patch.msgid.link/20260107161517.56357-2-haris.iqbal@ionos.com Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent c0def81 commit 33e3960

1 file changed

Lines changed: 20 additions & 5 deletions

File tree

drivers/infiniband/ulp/rtrs/rtrs-srv.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
595595
srv_path->mrs_num++) {
596596
struct rtrs_srv_mr *srv_mr = &srv_path->mrs[srv_path->mrs_num];
597597
struct scatterlist *s;
598-
int nr, nr_sgt, chunks;
598+
int nr, nr_sgt, chunks, ind;
599599

600600
sgt = &srv_mr->sgt;
601601
chunks = chunks_per_mr * srv_path->mrs_num;
@@ -625,7 +625,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
625625
}
626626
nr = ib_map_mr_sg(mr, sgt->sgl, nr_sgt,
627627
NULL, max_chunk_size);
628-
if (nr != nr_sgt) {
628+
if (nr < nr_sgt) {
629629
err = nr < 0 ? nr : -EINVAL;
630630
goto dereg_mr;
631631
}
@@ -641,9 +641,24 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
641641
goto dereg_mr;
642642
}
643643
}
644-
/* Eventually dma addr for each chunk can be cached */
645-
for_each_sg(sgt->sgl, s, nr_sgt, i)
646-
srv_path->dma_addr[chunks + i] = sg_dma_address(s);
644+
645+
/*
646+
* Cache DMA addresses by traversing sg entries. If
647+
* regions were merged, an inner loop is required to
648+
* populate the DMA address array by traversing larger
649+
* regions.
650+
*/
651+
ind = chunks;
652+
for_each_sg(sgt->sgl, s, nr_sgt, i) {
653+
unsigned int dma_len = sg_dma_len(s);
654+
u64 dma_addr = sg_dma_address(s);
655+
u64 dma_addr_end = dma_addr + dma_len;
656+
657+
do {
658+
srv_path->dma_addr[ind++] = dma_addr;
659+
dma_addr += max_chunk_size;
660+
} while (dma_addr < dma_addr_end);
661+
}
647662

648663
ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey));
649664
srv_mr->mr = mr;

0 commit comments

Comments
 (0)