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);
}
* 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;
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);
}
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);
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);
#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()
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;