]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
RDMA: Move DMA block iterator logic into dedicated files
authorLeon Romanovsky <leonro@nvidia.com>
Mon, 15 Jun 2026 22:52:14 +0000 (18:52 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 19 Jun 2026 11:42:37 +0000 (13:42 +0200)
[ Upstream commit 6094ea64c69520ed1e770e7c79c43412de202bfa ]

The DMA iterator logic was mixed into verbs and umem-specific code,
forcing all users to include rdma/ib_umem.h. Move the block iterator
logic into iter.c and rdma/iter.h so that rdma/ib_umem.h and
rdma/ib_verbs.h can be separated in a follow-up patch.

Link: https://patch.msgid.link/20260213-refactor-umem-v1-1-f3be85847922@nvidia.com
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20 files changed:
drivers/infiniband/core/Makefile
drivers/infiniband/core/iter.c [new file with mode: 0644]
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/bnxt_re/qplib_res.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/erdma/erdma_verbs.c
drivers/infiniband/hw/hns/hns_roce_alloc.c
drivers/infiniband/hw/irdma/main.h
drivers/infiniband/hw/mana/mana_ib.h
drivers/infiniband/hw/mlx4/mr.c
drivers/infiniband/hw/mlx5/mem.c
drivers/infiniband/hw/mlx5/umr.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qedr/verbs.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
include/rdma/ib_umem.h
include/rdma/ib_verbs.h
include/rdma/iter.h [new file with mode: 0644]

index 8ab4eea5a0a5e438894aef078c8a1350e01ff4ed..394d7e1f737511347b62fe2b9a3bd7aa55142434 100644 (file)
@@ -12,7 +12,7 @@ ib_core-y :=                  packer.o ud_header.o verbs.o cq.o rw.o sysfs.o \
                                roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
                                multicast.o mad.o smi.o agent.o mad_rmpp.o \
                                nldev.o restrack.o counters.o ib_core_uverbs.o \
-                               trace.o lag.o
+                               trace.o lag.o iter.o
 
 ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o
 ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o
diff --git a/drivers/infiniband/core/iter.c b/drivers/infiniband/core/iter.c
new file mode 100644 (file)
index 0000000..8e543d1
--- /dev/null
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */
+
+#include <linux/export.h>
+#include <rdma/iter.h>
+
+void __rdma_block_iter_start(struct ib_block_iter *biter,
+                            struct scatterlist *sglist, unsigned int nents,
+                            unsigned long pgsz)
+{
+       memset(biter, 0, sizeof(struct ib_block_iter));
+       biter->__sg = sglist;
+       biter->__sg_nents = nents;
+
+       /* Driver provides best block size to use */
+       biter->__pg_bit = __fls(pgsz);
+}
+EXPORT_SYMBOL(__rdma_block_iter_start);
+
+bool __rdma_block_iter_next(struct ib_block_iter *biter)
+{
+       unsigned int block_offset;
+       unsigned int delta;
+
+       if (!biter->__sg_nents || !biter->__sg)
+               return false;
+
+       biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
+       block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
+       delta = BIT_ULL(biter->__pg_bit) - block_offset;
+
+       while (biter->__sg_nents && biter->__sg &&
+              sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
+               delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
+               biter->__sg_advance = 0;
+               biter->__sg = sg_next(biter->__sg);
+               biter->__sg_nents--;
+       }
+       biter->__sg_advance += delta;
+
+       return true;
+}
+EXPORT_SYMBOL(__rdma_block_iter_next);
index 8dd96dc98fd31e328af902637a8802fd9d7f4472..dff87b5980aac06899c1ff3e6c2f5cabf8a55a9e 100644 (file)
@@ -3093,44 +3093,6 @@ int rdma_init_netdev(struct ib_device *device, u32 port_num,
 }
 EXPORT_SYMBOL(rdma_init_netdev);
 
-void __rdma_block_iter_start(struct ib_block_iter *biter,
-                            struct scatterlist *sglist, unsigned int nents,
-                            unsigned long pgsz)
-{
-       memset(biter, 0, sizeof(struct ib_block_iter));
-       biter->__sg = sglist;
-       biter->__sg_nents = nents;
-
-       /* Driver provides best block size to use */
-       biter->__pg_bit = __fls(pgsz);
-}
-EXPORT_SYMBOL(__rdma_block_iter_start);
-
-bool __rdma_block_iter_next(struct ib_block_iter *biter)
-{
-       unsigned int block_offset;
-       unsigned int delta;
-
-       if (!biter->__sg_nents || !biter->__sg)
-               return false;
-
-       biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
-       block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
-       delta = BIT_ULL(biter->__pg_bit) - block_offset;
-
-       while (biter->__sg_nents && biter->__sg &&
-              sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
-               delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
-               biter->__sg_advance = 0;
-               biter->__sg = sg_next(biter->__sg);
-               biter->__sg_nents--;
-       }
-       biter->__sg_advance += delta;
-
-       return true;
-}
-EXPORT_SYMBOL(__rdma_block_iter_next);
-
 /**
  * rdma_alloc_hw_stats_struct - Helper function to allocate dynamic struct
  *   for the drivers.
index dfb72a5adc916623a16f8936c2cba7dcc7c20523..cf8208f652d3bb639c9a81c2c8ffcb51ed09cb3f 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/if_vlan.h>
 #include <linux/vmalloc.h>
 #include <rdma/ib_verbs.h>
-#include <rdma/ib_umem.h>
+#include <rdma/iter.h>
 
 #include "roce_hsi.h"
 #include "qplib_res.h"
index a2c71a1d93d5a8fe0cd12c2a4f6f29b112b815eb..88db7e527728c069421f1ef4db012d40bb0814fd 100644 (file)
@@ -32,9 +32,9 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <rdma/ib_umem.h>
 #include <linux/atomic.h>
 #include <rdma/ib_user_verbs.h>
+#include <rdma/iter.h>
 
 #include "iw_cxgb4.h"
 
index fb6b29972fcce0e03e255ab1de8029d3141e84cb..ff36b7994af9e8c339435f260e3bdd4873698246 100644 (file)
@@ -9,9 +9,9 @@
 #include <linux/log2.h>
 
 #include <rdma/ib_addr.h>
-#include <rdma/ib_umem.h>
 #include <rdma/ib_user_verbs.h>
 #include <rdma/ib_verbs.h>
+#include <rdma/iter.h>
 #include <rdma/uverbs_ioctl.h>
 #define UVERBS_MODULE_NAME efa_ib
 #include <rdma/uverbs_named_ioctl.h>
index a50fb03c96431bc7984a746dabb3ef03a15ba3cc..bf5627e3f237bf80bbb1e853420cb5d6960cb85e 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/vmalloc.h>
 #include <net/addrconf.h>
 #include <rdma/erdma-abi.h>
-#include <rdma/ib_umem.h>
+#include <rdma/iter.h>
 #include <rdma/uverbs_ioctl.h>
 
 #include "erdma.h"
index 6ee911f6885b54bf76a4503e44ead6bd1afa4444..c21004814c3c255b115861d59a819af38623700f 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include <linux/vmalloc.h>
-#include <rdma/ib_umem.h>
+#include <rdma/iter.h>
 #include "hns_roce_device.h"
 
 void hns_roce_buf_free(struct hns_roce_dev *hr_dev, struct hns_roce_buf *buf)
index e8f5f8aaa56533f2d1cc3243ca589a45c53e7852..e5dc43442dff7f55e1227cf572735b7e958536cc 100644 (file)
@@ -37,8 +37,8 @@
 #include <rdma/rdma_cm.h>
 #include <rdma/iw_cm.h>
 #include <rdma/ib_user_verbs.h>
-#include <rdma/ib_umem.h>
 #include <rdma/ib_cache.h>
+#include <rdma/iter.h>
 #include <rdma/uverbs_ioctl.h>
 #include "osdep.h"
 #include "defs.h"
index bb9c6b1af24e16aa7258f48e75a6e1116dbf8470..3747c5186e24e97f916bba7737fd52d8e207ec59 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_mad.h>
-#include <rdma/ib_umem.h>
+#include <rdma/iter.h>
 #include <rdma/mana-abi.h>
 #include <rdma/uverbs_ioctl.h>
 
index 04c370fbdba0958a8b273168f79177219ae49b8e..e331c04967df8d1fee5a0de5889f96868d8e436b 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/slab.h>
 #include <rdma/ib_user_verbs.h>
+#include <rdma/iter.h>
 
 #include "mlx4_ib.h"
 
index af321f6ef7f5477a778e8898f245a31530156981..75d5b5672b5cf3dafbb60ba51cbe4a87fa5bc35c 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include <rdma/ib_umem_odp.h>
+#include <rdma/iter.h>
 #include "mlx5_ib.h"
 
 /*
index 80c665d152189d6f650ccfb561c446647a8498e6..562078b8f11a896a4fd811764bc64934474107a9 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
 
 #include <rdma/ib_umem_odp.h>
+#include <rdma/iter.h>
 #include "mlx5_ib.h"
 #include "umr.h"
 #include "wr.h"
index c01ac0e478c61ce9e27db490d67acddf6b418f16..d0ccdb68f2b82f130c499e5b8c22e10650898f95 100644 (file)
@@ -35,8 +35,8 @@
  */
 
 #include <rdma/ib_smi.h>
-#include <rdma/ib_umem.h>
 #include <rdma/ib_user_verbs.h>
+#include <rdma/iter.h>
 #include <rdma/uverbs_ioctl.h>
 
 #include <linux/sched.h>
index bbdf4619218deb9deb6faa902b471c4e56b409d1..6ae42ca04acc86741abfe5add817628ef2747742 100644 (file)
@@ -45,9 +45,9 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_user_verbs.h>
 #include <rdma/iw_cm.h>
-#include <rdma/ib_umem.h>
 #include <rdma/ib_addr.h>
 #include <rdma/ib_cache.h>
+#include <rdma/iter.h>
 #include <rdma/uverbs_ioctl.h>
 
 #include "ocrdma.h"
index 568a5b18803fc459b5a697af4c522d53e528a913..b5da3badfba65825a3d1b3472bd6ae23cbe98049 100644 (file)
@@ -39,9 +39,9 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_user_verbs.h>
 #include <rdma/iw_cm.h>
-#include <rdma/ib_umem.h>
 #include <rdma/ib_addr.h>
 #include <rdma/ib_cache.h>
+#include <rdma/iter.h>
 #include <rdma/uverbs_ioctl.h>
 
 #include <linux/qed/common_hsi.h>
index 763ddc6f25d1ae9aca097bcc3de9f9d86425baf4..23e547d4b3a715e5843b2f93853816b8dbf46ffd 100644 (file)
@@ -53,8 +53,8 @@
 #include <linux/pci.h>
 #include <linux/semaphore.h>
 #include <linux/workqueue.h>
-#include <rdma/ib_umem.h>
 #include <rdma/ib_verbs.h>
+#include <rdma/iter.h>
 #include <rdma/vmw_pvrdma-abi.h>
 
 #include "pvrdma_ring.h"
index b3c1a383906726c12f1d5c100a23636d5d5d198c..694f7e0876af81228ec0c9ebff766d7a013be1fd 100644 (file)
@@ -71,38 +71,6 @@ static inline size_t ib_umem_num_pages(struct ib_umem *umem)
 {
        return ib_umem_num_dma_blocks(umem, PAGE_SIZE);
 }
-
-static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
-                                               struct ib_umem *umem,
-                                               unsigned long pgsz)
-{
-       __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
-                               umem->sgt_append.sgt.nents, pgsz);
-       biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1);
-       biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz);
-}
-
-static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter)
-{
-       return __rdma_block_iter_next(biter) && biter->__sg_numblocks--;
-}
-
-/**
- * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
- * @umem: umem to iterate over
- * @biter: block iterator variable
- * @pgsz: Page size to split the list into
- *
- * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
- * returned DMA blocks will be aligned to pgsz and span the range:
- * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
- *
- * Performs exactly ib_umem_num_dma_blocks() iterations.
- */
-#define rdma_umem_for_each_dma_block(umem, biter, pgsz)                        \
-       for (__rdma_umem_block_iter_start(biter, umem, pgsz);                  \
-            __rdma_umem_block_iter_next(biter);)
-
 #ifdef CONFIG_INFINIBAND_USER_MEM
 
 struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
index c2b5de75daf252161aa74b73c6213aa1c58bc23c..a3d203ba238ddb0979d35c2d742e33b4fbbfe855 100644 (file)
@@ -2849,22 +2849,6 @@ struct ib_client {
        u8 no_kverbs_req:1;
 };
 
-/*
- * IB block DMA iterator
- *
- * Iterates the DMA-mapped SGL in contiguous memory blocks aligned
- * to a HW supported page size.
- */
-struct ib_block_iter {
-       /* internal states */
-       struct scatterlist *__sg;       /* sg holding the current aligned block */
-       dma_addr_t __dma_addr;          /* unaligned DMA address of this block */
-       size_t __sg_numblocks;          /* ib_umem_num_dma_blocks() */
-       unsigned int __sg_nents;        /* number of SG entries */
-       unsigned int __sg_advance;      /* number of bytes to advance in sg in next step */
-       unsigned int __pg_bit;          /* alignment of current block */
-};
-
 struct ib_device *_ib_alloc_device(size_t size);
 #define ib_alloc_device(drv_struct, member)                                    \
        container_of(_ib_alloc_device(sizeof(struct drv_struct) +              \
@@ -2886,38 +2870,6 @@ void ib_unregister_device_queued(struct ib_device *ib_dev);
 int ib_register_client   (struct ib_client *client);
 void ib_unregister_client(struct ib_client *client);
 
-void __rdma_block_iter_start(struct ib_block_iter *biter,
-                            struct scatterlist *sglist,
-                            unsigned int nents,
-                            unsigned long pgsz);
-bool __rdma_block_iter_next(struct ib_block_iter *biter);
-
-/**
- * rdma_block_iter_dma_address - get the aligned dma address of the current
- * block held by the block iterator.
- * @biter: block iterator holding the memory block
- */
-static inline dma_addr_t
-rdma_block_iter_dma_address(struct ib_block_iter *biter)
-{
-       return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1);
-}
-
-/**
- * rdma_for_each_block - iterate over contiguous memory blocks of the sg list
- * @sglist: sglist to iterate over
- * @biter: block iterator holding the memory block
- * @nents: maximum number of sg entries to iterate over
- * @pgsz: best HW supported page size to use
- *
- * Callers may use rdma_block_iter_dma_address() to get each
- * blocks aligned DMA address.
- */
-#define rdma_for_each_block(sglist, biter, nents, pgsz)                \
-       for (__rdma_block_iter_start(biter, sglist, nents,      \
-                                    pgsz);                     \
-            __rdma_block_iter_next(biter);)
-
 /**
  * ib_get_client_data - Get IB client context
  * @device:Device to get context for
diff --git a/include/rdma/iter.h b/include/rdma/iter.h
new file mode 100644 (file)
index 0000000..19d64ef
--- /dev/null
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */
+
+#ifndef _RDMA_ITER_H_
+#define _RDMA_ITER_H_
+
+#include <linux/scatterlist.h>
+#include <rdma/ib_umem.h>
+
+/**
+ * IB block DMA iterator
+ *
+ * Iterates the DMA-mapped SGL in contiguous memory blocks aligned
+ * to a HW supported page size.
+ */
+struct ib_block_iter {
+       /* internal states */
+       struct scatterlist *__sg;       /* sg holding the current aligned block */
+       dma_addr_t __dma_addr;          /* unaligned DMA address of this block */
+       size_t __sg_numblocks;          /* ib_umem_num_dma_blocks() */
+       unsigned int __sg_nents;        /* number of SG entries */
+       unsigned int __sg_advance;      /* number of bytes to advance in sg in next step */
+       unsigned int __pg_bit;          /* alignment of current block */
+};
+
+void __rdma_block_iter_start(struct ib_block_iter *biter,
+                            struct scatterlist *sglist,
+                            unsigned int nents,
+                            unsigned long pgsz);
+bool __rdma_block_iter_next(struct ib_block_iter *biter);
+
+/**
+ * rdma_block_iter_dma_address - get the aligned dma address of the current
+ * block held by the block iterator.
+ * @biter: block iterator holding the memory block
+ */
+static inline dma_addr_t
+rdma_block_iter_dma_address(struct ib_block_iter *biter)
+{
+       return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1);
+}
+
+/**
+ * rdma_for_each_block - iterate over contiguous memory blocks of the sg list
+ * @sglist: sglist to iterate over
+ * @biter: block iterator holding the memory block
+ * @nents: maximum number of sg entries to iterate over
+ * @pgsz: best HW supported page size to use
+ *
+ * Callers may use rdma_block_iter_dma_address() to get each
+ * blocks aligned DMA address.
+ */
+#define rdma_for_each_block(sglist, biter, nents, pgsz)                \
+       for (__rdma_block_iter_start(biter, sglist, nents,      \
+                                    pgsz);                     \
+            __rdma_block_iter_next(biter);)
+
+static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
+                                               struct ib_umem *umem,
+                                               unsigned long pgsz)
+{
+       __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
+                               umem->sgt_append.sgt.nents, pgsz);
+       biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1);
+       biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz);
+}
+
+static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter)
+{
+       return __rdma_block_iter_next(biter) && biter->__sg_numblocks--;
+}
+
+/**
+ * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
+ * @umem: umem to iterate over
+ * @pgsz: Page size to split the list into
+ *
+ * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
+ * returned DMA blocks will be aligned to pgsz and span the range:
+ * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
+ *
+ * Performs exactly ib_umem_num_dma_blocks() iterations.
+ */
+#define rdma_umem_for_each_dma_block(umem, biter, pgsz)                        \
+       for (__rdma_umem_block_iter_start(biter, umem, pgsz);                  \
+            __rdma_umem_block_iter_next(biter);)
+
+#endif /* _RDMA_ITER_H_ */