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:
Bernard Metzler 2026-05-11 16:11:49 +02:00 committed by Leon Romanovsky
parent dd7f5374d1
commit c620705561
3 changed files with 33 additions and 33 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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;