mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
RDMA/siw: use kzalloc_flex
Simplify umem allocation by using flexible array member. Add __counted_by to get extra runtime analysis. Suggested-by: Rosen Penev <rosenp@gmail.com> Signed-off-by: Bernard Metzler <bernard.metzler@linux.dev> Link: https://patch.msgid.link/20260511141149.52362-1-bernard.metzler@linux.dev Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
dd7f5374d1
commit
c620705561
|
|
@ -119,9 +119,10 @@ struct siw_page_chunk {
|
|||
|
||||
struct siw_umem {
|
||||
struct ib_umem *base_mem;
|
||||
struct siw_page_chunk *page_chunk;
|
||||
int num_pages;
|
||||
unsigned int num_pages;
|
||||
unsigned int num_chunks;
|
||||
u64 fp_addr; /* First page base address */
|
||||
struct siw_page_chunk page_chunk[] __counted_by(num_chunks);
|
||||
};
|
||||
|
||||
struct siw_pble {
|
||||
|
|
|
|||
|
|
@ -41,16 +41,14 @@ struct siw_mem *siw_mem_id2obj(struct siw_device *sdev, int stag_index)
|
|||
|
||||
void siw_umem_release(struct siw_umem *umem)
|
||||
{
|
||||
int i, num_pages = umem->num_pages;
|
||||
unsigned int i, num_chunks = umem->num_chunks;
|
||||
|
||||
if (umem->base_mem)
|
||||
ib_umem_release(umem->base_mem);
|
||||
|
||||
for (i = 0; num_pages > 0; i++) {
|
||||
for (i = 0; i < num_chunks; i++)
|
||||
kfree(umem->page_chunk[i].plist);
|
||||
num_pages -= PAGES_PER_CHUNK;
|
||||
}
|
||||
kfree(umem->page_chunk);
|
||||
|
||||
kfree(umem);
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +186,7 @@ int siw_check_mem(struct ib_pd *pd, struct siw_mem *mem, u64 addr,
|
|||
* lookup is being done and mem is not released it check fails.
|
||||
*/
|
||||
int siw_check_sge(struct ib_pd *pd, struct siw_sge *sge, struct siw_mem *mem[],
|
||||
enum ib_access_flags perms, u32 off, int len)
|
||||
enum ib_access_flags perms, u32 off, u32 len)
|
||||
{
|
||||
struct siw_device *sdev = to_siw_dev(pd->device);
|
||||
struct siw_mem *new = NULL;
|
||||
|
|
@ -338,25 +336,20 @@ struct siw_umem *siw_umem_get(struct ib_device *base_dev, u64 start,
|
|||
struct sg_page_iter sg_iter;
|
||||
struct sg_table *sgt;
|
||||
u64 first_page_va;
|
||||
int num_pages, num_chunks, i, rv = 0;
|
||||
unsigned int num_pages, num_chunks, i;
|
||||
int rv = 0;
|
||||
|
||||
if (!len)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
first_page_va = start & PAGE_MASK;
|
||||
num_pages = PAGE_ALIGN(start + len - first_page_va) >> PAGE_SHIFT;
|
||||
num_chunks = (num_pages >> CHUNK_SHIFT) + 1;
|
||||
num_chunks = ((num_pages - 1) >> CHUNK_SHIFT) + 1;
|
||||
|
||||
umem = kzalloc_obj(*umem);
|
||||
umem = kzalloc_flex(*umem, page_chunk, num_chunks);
|
||||
if (!umem)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
umem->page_chunk =
|
||||
kzalloc_objs(struct siw_page_chunk, num_chunks);
|
||||
if (!umem->page_chunk) {
|
||||
rv = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
base_mem = ib_umem_get(base_dev, start, len, rights);
|
||||
if (IS_ERR(base_mem)) {
|
||||
rv = PTR_ERR(base_mem);
|
||||
|
|
@ -365,33 +358,40 @@ struct siw_umem *siw_umem_get(struct ib_device *base_dev, u64 start,
|
|||
}
|
||||
umem->fp_addr = first_page_va;
|
||||
umem->base_mem = base_mem;
|
||||
umem->num_pages = num_pages;
|
||||
umem->num_chunks = num_chunks;
|
||||
|
||||
sgt = &base_mem->sgt_append.sgt;
|
||||
__sg_page_iter_start(&sg_iter, sgt->sgl, sgt->orig_nents, 0);
|
||||
|
||||
if (!__sg_page_iter_next(&sg_iter)) {
|
||||
rv = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
for (i = 0; num_pages > 0; i++) {
|
||||
int nents = min_t(int, num_pages, PAGES_PER_CHUNK);
|
||||
struct page **plist =
|
||||
kzalloc_objs(struct page *, nents);
|
||||
for (i = 0; i < num_chunks; i++) {
|
||||
struct page **plist;
|
||||
unsigned int pix, nents = min(num_pages, PAGES_PER_CHUNK);
|
||||
|
||||
plist = kzalloc_objs(struct page *, nents);
|
||||
if (!plist) {
|
||||
rv = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
umem->page_chunk[i].plist = plist;
|
||||
while (nents--) {
|
||||
*plist = sg_page_iter_page(&sg_iter);
|
||||
umem->num_pages++;
|
||||
num_pages--;
|
||||
plist++;
|
||||
|
||||
for (pix = 0; pix < nents; pix++) {
|
||||
if (!__sg_page_iter_next(&sg_iter))
|
||||
break;
|
||||
plist[pix] = sg_page_iter_page(&sg_iter);
|
||||
num_pages--;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_pages) {
|
||||
/*
|
||||
* Unexpected size of sg list provided by ib_umem_get()
|
||||
*/
|
||||
siw_dbg(base_dev, "Short SG list, missing %u pages\n",
|
||||
num_pages);
|
||||
rv = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
return umem;
|
||||
err_out:
|
||||
siw_umem_release(umem);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ int siw_check_mem(struct ib_pd *pd, struct siw_mem *mem, u64 addr,
|
|||
enum ib_access_flags perms, int len);
|
||||
int siw_check_sge(struct ib_pd *pd, struct siw_sge *sge,
|
||||
struct siw_mem *mem[], enum ib_access_flags perms,
|
||||
u32 off, int len);
|
||||
u32 off, u32 len);
|
||||
void siw_wqe_put_mem(struct siw_wqe *wqe, enum siw_opcode op);
|
||||
int siw_mr_add_mem(struct siw_mr *mr, struct ib_pd *pd, void *mem_obj,
|
||||
u64 start, u64 len, int rights);
|
||||
|
|
@ -45,7 +45,6 @@ static inline void siw_unref_mem_sgl(struct siw_mem **mem, unsigned int num_sge)
|
|||
#define CHUNK_SHIFT 9 /* sets number of pages per chunk */
|
||||
#define PAGES_PER_CHUNK (_AC(1, UL) << CHUNK_SHIFT)
|
||||
#define CHUNK_MASK (~(PAGES_PER_CHUNK - 1))
|
||||
#define PAGE_CHUNK_SIZE (PAGES_PER_CHUNK * sizeof(struct page *))
|
||||
|
||||
/*
|
||||
* siw_get_upage()
|
||||
|
|
@ -61,7 +60,7 @@ static inline struct page *siw_get_upage(struct siw_umem *umem, u64 addr)
|
|||
chunk_idx = page_idx >> CHUNK_SHIFT,
|
||||
page_in_chunk = page_idx & ~CHUNK_MASK;
|
||||
|
||||
if (likely(page_idx < umem->num_pages))
|
||||
if (page_idx < umem->num_pages)
|
||||
return umem->page_chunk[chunk_idx].plist[page_in_chunk];
|
||||
|
||||
return NULL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user