]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/siw: use kzalloc_flex
authorBernard Metzler <bernard.metzler@linux.dev>
Mon, 11 May 2026 14:11:49 +0000 (16:11 +0200)
committerLeon Romanovsky <leon@kernel.org>
Mon, 18 May 2026 08:58:42 +0000 (04:58 -0400)
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>
drivers/infiniband/sw/siw/siw.h
drivers/infiniband/sw/siw/siw_mem.c
drivers/infiniband/sw/siw/siw_mem.h

index f5fd71717b8073dd0abbbdf262da35c83259237b..dbc998248b1e9f2527c58a530b702495c0de9308 100644 (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 {
index 98c802b3ed723719b7f24a62bde9f901c9cdb09a..4df792ebe02fae23056854d96b7cd5bff0735766 100644 (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);
index 8e769d30e2acd085477a6ed0063e8259879c4180..e4f3a5a4f81df73f91e6b2fb81c5d817919cc6c0 100644 (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;