提交 5b7ee8a4 编写于 作者: X Xi Wang 提交者: Yang Yingliang

RDMA/verbs: Add a DMA iterator to return aligned contiguous memory blocks

driver inclusion
category: bugfix
bugzilla: NA
CVE: NA

This helper iterates over a DMA-mapped SGL and returns contiguous memory
blocks aligned to a HW supported page size.
Suggested-by: NJason Gunthorpe <jgg@ziepe.ca>
Signed-off-by: NShiraz Saleem <shiraz.saleem@intel.com>
Signed-off-by: NJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: NXi Wang <wangxi11@huawei.com>
Signed-off-by: NShunfeng Yang <yangshunfeng2@huawei.com>
Reviewed-by: Nchunzhi hu <huchunzhi@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 3bf49a0c
...@@ -2628,3 +2628,37 @@ void ib_drain_qp(struct ib_qp *qp) ...@@ -2628,3 +2628,37 @@ void ib_drain_qp(struct ib_qp *qp)
ib_drain_rq(qp); ib_drain_rq(qp);
} }
EXPORT_SYMBOL(ib_drain_qp); EXPORT_SYMBOL(ib_drain_qp);
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;
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);
biter->__sg_advance += BIT_ULL(biter->__pg_bit) - block_offset;
if (biter->__sg_advance >= sg_dma_len(biter->__sg)) {
biter->__sg_advance = 0;
biter->__sg = sg_next(biter->__sg);
biter->__sg_nents--;
}
return true;
}
EXPORT_SYMBOL(__rdma_block_iter_next);
...@@ -2629,6 +2629,21 @@ struct ib_client { ...@@ -2629,6 +2629,21 @@ struct ib_client {
struct list_head list; struct list_head list;
}; };
/*
* 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 */
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); struct ib_device *ib_alloc_device(size_t size);
void ib_dealloc_device(struct ib_device *device); void ib_dealloc_device(struct ib_device *device);
...@@ -2642,6 +2657,38 @@ void ib_unregister_device(struct ib_device *device); ...@@ -2642,6 +2657,38 @@ void ib_unregister_device(struct ib_device *device);
int ib_register_client (struct ib_client *client); int ib_register_client (struct ib_client *client);
void ib_unregister_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);)
void *ib_get_client_data(struct ib_device *device, struct ib_client *client); void *ib_get_client_data(struct ib_device *device, struct ib_client *client);
void ib_set_client_data(struct ib_device *device, struct ib_client *client, void ib_set_client_data(struct ib_device *device, struct ib_client *client,
void *data); void *data);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册