Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889/* 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_trdma_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_ */