Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

RDMA/rtrs-srv: fix SG mapping

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: 9cb837480424 ("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>

authored by

Roman Penyaev and committed by
Leon Romanovsky
83835f7c 325e3b54

+20 -5
+20 -5
drivers/infiniband/ulp/rtrs/rtrs-srv.c
··· 595 595 srv_path->mrs_num++) { 596 596 struct rtrs_srv_mr *srv_mr = &srv_path->mrs[srv_path->mrs_num]; 597 597 struct scatterlist *s; 598 - int nr, nr_sgt, chunks; 598 + int nr, nr_sgt, chunks, ind; 599 599 600 600 sgt = &srv_mr->sgt; 601 601 chunks = chunks_per_mr * srv_path->mrs_num; ··· 625 625 } 626 626 nr = ib_map_mr_sg(mr, sgt->sgl, nr_sgt, 627 627 NULL, max_chunk_size); 628 - if (nr != nr_sgt) { 628 + if (nr < nr_sgt) { 629 629 err = nr < 0 ? nr : -EINVAL; 630 630 goto dereg_mr; 631 631 } ··· 641 641 goto dereg_mr; 642 642 } 643 643 } 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 + } 647 662 648 663 ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey)); 649 664 srv_mr->mr = mr;