mirror of https://github.com/torvalds/linux.git
89 lines
3.0 KiB
C
89 lines
3.0 KiB
C
/* 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_ */
|