Commit eeb8461e authored by Yishai Hadas's avatar Yishai Hadas Committed by Roland Dreier

IB: Refactor umem to use linear SG table

This patch refactors the IB core umem code and vendor drivers to use a
linear (chained) SG table instead of chunk list.  With this change the
relevant code becomes clearer—no need for nested loops to build and
use umem.
Signed-off-by: default avatarShachar Raindel <raindel@mellanox.com>
Signed-off-by: default avatarYishai Hadas <yishaih@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent cfbf8d48
...@@ -42,29 +42,29 @@ ...@@ -42,29 +42,29 @@
#include "uverbs.h" #include "uverbs.h"
#define IB_UMEM_MAX_PAGE_CHUNK \
((PAGE_SIZE - offsetof(struct ib_umem_chunk, page_list)) / \
((void *) &((struct ib_umem_chunk *) 0)->page_list[1] - \
(void *) &((struct ib_umem_chunk *) 0)->page_list[0]))
static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty) static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty)
{ {
struct ib_umem_chunk *chunk, *tmp; struct scatterlist *sg;
struct page *page;
int i; int i;
list_for_each_entry_safe(chunk, tmp, &umem->chunk_list, list) { if (umem->nmap > 0)
ib_dma_unmap_sg(dev, chunk->page_list, ib_dma_unmap_sg(dev, umem->sg_head.sgl,
chunk->nents, DMA_BIDIRECTIONAL); umem->nmap,
for (i = 0; i < chunk->nents; ++i) { DMA_BIDIRECTIONAL);
struct page *page = sg_page(&chunk->page_list[i]);
for_each_sg(umem->sg_head.sgl, sg, umem->npages, i) {
page = sg_page(sg);
if (umem->writable && dirty) if (umem->writable && dirty)
set_page_dirty_lock(page); set_page_dirty_lock(page);
put_page(page); put_page(page);
} }
kfree(chunk); sg_free_table(&umem->sg_head);
} return;
} }
/** /**
...@@ -81,15 +81,15 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, ...@@ -81,15 +81,15 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
struct ib_umem *umem; struct ib_umem *umem;
struct page **page_list; struct page **page_list;
struct vm_area_struct **vma_list; struct vm_area_struct **vma_list;
struct ib_umem_chunk *chunk;
unsigned long locked; unsigned long locked;
unsigned long lock_limit; unsigned long lock_limit;
unsigned long cur_base; unsigned long cur_base;
unsigned long npages; unsigned long npages;
int ret; int ret;
int off;
int i; int i;
DEFINE_DMA_ATTRS(attrs); DEFINE_DMA_ATTRS(attrs);
struct scatterlist *sg, *sg_list_start;
int need_release = 0;
if (dmasync) if (dmasync)
dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs); dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
...@@ -97,7 +97,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, ...@@ -97,7 +97,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
if (!can_do_mlock()) if (!can_do_mlock())
return ERR_PTR(-EPERM); return ERR_PTR(-EPERM);
umem = kmalloc(sizeof *umem, GFP_KERNEL); umem = kzalloc(sizeof *umem, GFP_KERNEL);
if (!umem) if (!umem)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -117,8 +117,6 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, ...@@ -117,8 +117,6 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
/* We assume the memory is from hugetlb until proved otherwise */ /* We assume the memory is from hugetlb until proved otherwise */
umem->hugetlb = 1; umem->hugetlb = 1;
INIT_LIST_HEAD(&umem->chunk_list);
page_list = (struct page **) __get_free_page(GFP_KERNEL); page_list = (struct page **) __get_free_page(GFP_KERNEL);
if (!page_list) { if (!page_list) {
kfree(umem); kfree(umem);
...@@ -147,7 +145,18 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, ...@@ -147,7 +145,18 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
cur_base = addr & PAGE_MASK; cur_base = addr & PAGE_MASK;
ret = 0; if (npages == 0) {
ret = -EINVAL;
goto out;
}
ret = sg_alloc_table(&umem->sg_head, npages, GFP_KERNEL);
if (ret)
goto out;
need_release = 1;
sg_list_start = umem->sg_head.sgl;
while (npages) { while (npages) {
ret = get_user_pages(current, current->mm, cur_base, ret = get_user_pages(current, current->mm, cur_base,
min_t(unsigned long, npages, min_t(unsigned long, npages,
...@@ -157,53 +166,37 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, ...@@ -157,53 +166,37 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
if (ret < 0) if (ret < 0)
goto out; goto out;
umem->npages += ret;
cur_base += ret * PAGE_SIZE; cur_base += ret * PAGE_SIZE;
npages -= ret; npages -= ret;
off = 0; for_each_sg(sg_list_start, sg, ret, i) {
if (vma_list && !is_vm_hugetlb_page(vma_list[i]))
umem->hugetlb = 0;
while (ret) { sg_set_page(sg, page_list[i], PAGE_SIZE, 0);
chunk = kmalloc(sizeof *chunk + sizeof (struct scatterlist) *
min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK),
GFP_KERNEL);
if (!chunk) {
ret = -ENOMEM;
goto out;
} }
chunk->nents = min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK); /* preparing for next loop */
sg_init_table(chunk->page_list, chunk->nents); sg_list_start = sg;
for (i = 0; i < chunk->nents; ++i) {
if (vma_list &&
!is_vm_hugetlb_page(vma_list[i + off]))
umem->hugetlb = 0;
sg_set_page(&chunk->page_list[i], page_list[i + off], PAGE_SIZE, 0);
} }
chunk->nmap = ib_dma_map_sg_attrs(context->device, umem->nmap = ib_dma_map_sg_attrs(context->device,
&chunk->page_list[0], umem->sg_head.sgl,
chunk->nents, umem->npages,
DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL,
&attrs); &attrs);
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
put_page(sg_page(&chunk->page_list[i]));
kfree(chunk);
if (umem->nmap <= 0) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
ret -= chunk->nents;
off += chunk->nents;
list_add_tail(&chunk->list, &umem->chunk_list);
}
ret = 0; ret = 0;
}
out: out:
if (ret < 0) { if (ret < 0) {
if (need_release)
__ib_umem_release(context->device, umem, 0); __ib_umem_release(context->device, umem, 0);
kfree(umem); kfree(umem);
} else } else
...@@ -278,17 +271,16 @@ EXPORT_SYMBOL(ib_umem_release); ...@@ -278,17 +271,16 @@ EXPORT_SYMBOL(ib_umem_release);
int ib_umem_page_count(struct ib_umem *umem) int ib_umem_page_count(struct ib_umem *umem)
{ {
struct ib_umem_chunk *chunk;
int shift; int shift;
int i; int i;
int n; int n;
struct scatterlist *sg;
shift = ilog2(umem->page_size); shift = ilog2(umem->page_size);
n = 0; n = 0;
list_for_each_entry(chunk, &umem->chunk_list, list) for_each_sg(umem->sg_head.sgl, sg, umem->nmap, i)
for (i = 0; i < chunk->nmap; ++i) n += sg_dma_len(sg) >> shift;
n += sg_dma_len(&chunk->page_list[i]) >> shift;
return n; return n;
} }
......
...@@ -431,9 +431,9 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -431,9 +431,9 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 *pages; u64 *pages;
u64 kva = 0; u64 kva = 0;
int shift, n, len; int shift, n, len;
int i, j, k; int i, k, entry;
int err = 0; int err = 0;
struct ib_umem_chunk *chunk; struct scatterlist *sg;
struct c2_pd *c2pd = to_c2pd(pd); struct c2_pd *c2pd = to_c2pd(pd);
struct c2_mr *c2mr; struct c2_mr *c2mr;
...@@ -452,10 +452,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -452,10 +452,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
} }
shift = ffs(c2mr->umem->page_size) - 1; shift = ffs(c2mr->umem->page_size) - 1;
n = c2mr->umem->nmap;
n = 0;
list_for_each_entry(chunk, &c2mr->umem->chunk_list, list)
n += chunk->nents;
pages = kmalloc(n * sizeof(u64), GFP_KERNEL); pages = kmalloc(n * sizeof(u64), GFP_KERNEL);
if (!pages) { if (!pages) {
...@@ -464,16 +461,14 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -464,16 +461,14 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
} }
i = 0; i = 0;
list_for_each_entry(chunk, &c2mr->umem->chunk_list, list) { for_each_sg(c2mr->umem->sg_head.sgl, sg, c2mr->umem->nmap, entry) {
for (j = 0; j < chunk->nmap; ++j) { len = sg_dma_len(sg) >> shift;
len = sg_dma_len(&chunk->page_list[j]) >> shift;
for (k = 0; k < len; ++k) { for (k = 0; k < len; ++k) {
pages[i++] = pages[i++] =
sg_dma_address(&chunk->page_list[j]) + sg_dma_address(sg) +
(c2mr->umem->page_size * k); (c2mr->umem->page_size * k);
} }
} }
}
kva = virt; kva = virt;
err = c2_nsmr_register_phys_kern(to_c2dev(pd->device), err = c2_nsmr_register_phys_kern(to_c2dev(pd->device),
......
...@@ -618,14 +618,13 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -618,14 +618,13 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
{ {
__be64 *pages; __be64 *pages;
int shift, n, len; int shift, n, len;
int i, j, k; int i, k, entry;
int err = 0; int err = 0;
struct ib_umem_chunk *chunk;
struct iwch_dev *rhp; struct iwch_dev *rhp;
struct iwch_pd *php; struct iwch_pd *php;
struct iwch_mr *mhp; struct iwch_mr *mhp;
struct iwch_reg_user_mr_resp uresp; struct iwch_reg_user_mr_resp uresp;
struct scatterlist *sg;
PDBG("%s ib_pd %p\n", __func__, pd); PDBG("%s ib_pd %p\n", __func__, pd);
php = to_iwch_pd(pd); php = to_iwch_pd(pd);
...@@ -645,9 +644,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -645,9 +644,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
shift = ffs(mhp->umem->page_size) - 1; shift = ffs(mhp->umem->page_size) - 1;
n = 0; n = mhp->umem->nmap;
list_for_each_entry(chunk, &mhp->umem->chunk_list, list)
n += chunk->nents;
err = iwch_alloc_pbl(mhp, n); err = iwch_alloc_pbl(mhp, n);
if (err) if (err)
...@@ -661,12 +658,10 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -661,12 +658,10 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
i = n = 0; i = n = 0;
list_for_each_entry(chunk, &mhp->umem->chunk_list, list) for_each_sg(mhp->umem->sg_head.sgl, sg, mhp->umem->nmap, entry) {
for (j = 0; j < chunk->nmap; ++j) { len = sg_dma_len(sg) >> shift;
len = sg_dma_len(&chunk->page_list[j]) >> shift;
for (k = 0; k < len; ++k) { for (k = 0; k < len; ++k) {
pages[i++] = cpu_to_be64(sg_dma_address( pages[i++] = cpu_to_be64(sg_dma_address(sg) +
&chunk->page_list[j]) +
mhp->umem->page_size * k); mhp->umem->page_size * k);
if (i == PAGE_SIZE / sizeof *pages) { if (i == PAGE_SIZE / sizeof *pages) {
err = iwch_write_pbl(mhp, pages, i, n); err = iwch_write_pbl(mhp, pages, i, n);
......
...@@ -678,9 +678,9 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -678,9 +678,9 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
{ {
__be64 *pages; __be64 *pages;
int shift, n, len; int shift, n, len;
int i, j, k; int i, k, entry;
int err = 0; int err = 0;
struct ib_umem_chunk *chunk; struct scatterlist *sg;
struct c4iw_dev *rhp; struct c4iw_dev *rhp;
struct c4iw_pd *php; struct c4iw_pd *php;
struct c4iw_mr *mhp; struct c4iw_mr *mhp;
...@@ -710,10 +710,7 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -710,10 +710,7 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
shift = ffs(mhp->umem->page_size) - 1; shift = ffs(mhp->umem->page_size) - 1;
n = 0; n = mhp->umem->nmap;
list_for_each_entry(chunk, &mhp->umem->chunk_list, list)
n += chunk->nents;
err = alloc_pbl(mhp, n); err = alloc_pbl(mhp, n);
if (err) if (err)
goto err; goto err;
...@@ -726,12 +723,10 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -726,12 +723,10 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
i = n = 0; i = n = 0;
list_for_each_entry(chunk, &mhp->umem->chunk_list, list) for_each_sg(mhp->umem->sg_head.sgl, sg, mhp->umem->nmap, entry) {
for (j = 0; j < chunk->nmap; ++j) { len = sg_dma_len(sg) >> shift;
len = sg_dma_len(&chunk->page_list[j]) >> shift;
for (k = 0; k < len; ++k) { for (k = 0; k < len; ++k) {
pages[i++] = cpu_to_be64(sg_dma_address( pages[i++] = cpu_to_be64(sg_dma_address(sg) +
&chunk->page_list[j]) +
mhp->umem->page_size * k); mhp->umem->page_size * k);
if (i == PAGE_SIZE / sizeof *pages) { if (i == PAGE_SIZE / sizeof *pages) {
err = write_pbl(&mhp->rhp->rdev, err = write_pbl(&mhp->rhp->rdev,
......
...@@ -322,7 +322,7 @@ struct ehca_mr_pginfo { ...@@ -322,7 +322,7 @@ struct ehca_mr_pginfo {
} phy; } phy;
struct { /* type EHCA_MR_PGI_USER section */ struct { /* type EHCA_MR_PGI_USER section */
struct ib_umem *region; struct ib_umem *region;
struct ib_umem_chunk *next_chunk; struct scatterlist *next_sg;
u64 next_nmap; u64 next_nmap;
} usr; } usr;
struct { /* type EHCA_MR_PGI_FMR section */ struct { /* type EHCA_MR_PGI_FMR section */
......
...@@ -400,10 +400,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -400,10 +400,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
pginfo.num_hwpages = num_hwpages; pginfo.num_hwpages = num_hwpages;
pginfo.u.usr.region = e_mr->umem; pginfo.u.usr.region = e_mr->umem;
pginfo.next_hwpage = e_mr->umem->offset / hwpage_size; pginfo.next_hwpage = e_mr->umem->offset / hwpage_size;
pginfo.u.usr.next_chunk = list_prepare_entry(pginfo.u.usr.next_chunk, pginfo.u.usr.next_sg = pginfo.u.usr.region->sg_head.sgl;
(&e_mr->umem->chunk_list),
list);
ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags, ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags,
e_pd, &pginfo, &e_mr->ib.ib_mr.lkey, e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
&e_mr->ib.ib_mr.rkey, EHCA_REG_MR); &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
...@@ -1858,30 +1855,23 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo, ...@@ -1858,30 +1855,23 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
u64 *kpage) u64 *kpage)
{ {
int ret = 0; int ret = 0;
struct ib_umem_chunk *prev_chunk;
struct ib_umem_chunk *chunk;
u64 pgaddr; u64 pgaddr;
u32 i = 0;
u32 j = 0; u32 j = 0;
int hwpages_per_kpage = PAGE_SIZE / pginfo->hwpage_size; int hwpages_per_kpage = PAGE_SIZE / pginfo->hwpage_size;
struct scatterlist **sg = &pginfo->u.usr.next_sg;
/* loop over desired chunk entries */ while (*sg != NULL) {
chunk = pginfo->u.usr.next_chunk; pgaddr = page_to_pfn(sg_page(*sg))
prev_chunk = pginfo->u.usr.next_chunk; << PAGE_SHIFT;
list_for_each_entry_continue(
chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
pgaddr = page_to_pfn(sg_page(&chunk->page_list[i]))
<< PAGE_SHIFT ;
*kpage = pgaddr + (pginfo->next_hwpage * *kpage = pgaddr + (pginfo->next_hwpage *
pginfo->hwpage_size); pginfo->hwpage_size);
if ( !(*kpage) ) { if (!(*kpage)) {
ehca_gen_err("pgaddr=%llx " ehca_gen_err("pgaddr=%llx "
"chunk->page_list[i]=%llx " "sg_dma_address=%llx "
"i=%x next_hwpage=%llx", "entry=%llx next_hwpage=%llx",
pgaddr, (u64)sg_dma_address( pgaddr, (u64)sg_dma_address(*sg),
&chunk->page_list[i]), pginfo->u.usr.next_nmap,
i, pginfo->next_hwpage); pginfo->next_hwpage);
return -EFAULT; return -EFAULT;
} }
(pginfo->hwpage_cnt)++; (pginfo->hwpage_cnt)++;
...@@ -1891,28 +1881,13 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo, ...@@ -1891,28 +1881,13 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
(pginfo->kpage_cnt)++; (pginfo->kpage_cnt)++;
(pginfo->u.usr.next_nmap)++; (pginfo->u.usr.next_nmap)++;
pginfo->next_hwpage = 0; pginfo->next_hwpage = 0;
i++; *sg = sg_next(*sg);
} }
j++; j++;
if (j >= number) break; if (j >= number)
}
if ((pginfo->u.usr.next_nmap >= chunk->nmap) &&
(j >= number)) {
pginfo->u.usr.next_nmap = 0;
prev_chunk = chunk;
break; break;
} else if (pginfo->u.usr.next_nmap >= chunk->nmap) {
pginfo->u.usr.next_nmap = 0;
prev_chunk = chunk;
} else if (j >= number)
break;
else
prev_chunk = chunk;
} }
pginfo->u.usr.next_chunk =
list_prepare_entry(prev_chunk,
(&(pginfo->u.usr.region->chunk_list)),
list);
return ret; return ret;
} }
...@@ -1920,20 +1895,19 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo, ...@@ -1920,20 +1895,19 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
* check given pages for contiguous layout * check given pages for contiguous layout
* last page addr is returned in prev_pgaddr for further check * last page addr is returned in prev_pgaddr for further check
*/ */
static int ehca_check_kpages_per_ate(struct scatterlist *page_list, static int ehca_check_kpages_per_ate(struct scatterlist **sg,
int start_idx, int end_idx, int num_pages,
u64 *prev_pgaddr) u64 *prev_pgaddr)
{ {
int t; for (; *sg && num_pages > 0; *sg = sg_next(*sg), num_pages--) {
for (t = start_idx; t <= end_idx; t++) { u64 pgaddr = page_to_pfn(sg_page(*sg)) << PAGE_SHIFT;
u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
if (ehca_debug_level >= 3) if (ehca_debug_level >= 3)
ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr, ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr,
*(u64 *)__va(pgaddr)); *(u64 *)__va(pgaddr));
if (pgaddr - PAGE_SIZE != *prev_pgaddr) { if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
ehca_gen_err("uncontiguous page found pgaddr=%llx " ehca_gen_err("uncontiguous page found pgaddr=%llx "
"prev_pgaddr=%llx page_list_i=%x", "prev_pgaddr=%llx entries_left_in_hwpage=%x",
pgaddr, *prev_pgaddr, t); pgaddr, *prev_pgaddr, num_pages);
return -EINVAL; return -EINVAL;
} }
*prev_pgaddr = pgaddr; *prev_pgaddr = pgaddr;
...@@ -1947,27 +1921,21 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo, ...@@ -1947,27 +1921,21 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
u64 *kpage) u64 *kpage)
{ {
int ret = 0; int ret = 0;
struct ib_umem_chunk *prev_chunk;
struct ib_umem_chunk *chunk;
u64 pgaddr, prev_pgaddr; u64 pgaddr, prev_pgaddr;
u32 i = 0;
u32 j = 0; u32 j = 0;
int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE; int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE;
int nr_kpages = kpages_per_hwpage; int nr_kpages = kpages_per_hwpage;
struct scatterlist **sg = &pginfo->u.usr.next_sg;
while (*sg != NULL) {
/* loop over desired chunk entries */
chunk = pginfo->u.usr.next_chunk;
prev_chunk = pginfo->u.usr.next_chunk;
list_for_each_entry_continue(
chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
if (nr_kpages == kpages_per_hwpage) { if (nr_kpages == kpages_per_hwpage) {
pgaddr = ( page_to_pfn(sg_page(&chunk->page_list[i])) pgaddr = (page_to_pfn(sg_page(*sg))
<< PAGE_SHIFT ); << PAGE_SHIFT);
*kpage = pgaddr; *kpage = pgaddr;
if ( !(*kpage) ) { if (!(*kpage)) {
ehca_gen_err("pgaddr=%llx i=%x", ehca_gen_err("pgaddr=%llx entry=%llx",
pgaddr, i); pgaddr, pginfo->u.usr.next_nmap);
ret = -EFAULT; ret = -EFAULT;
return ret; return ret;
} }
...@@ -1979,9 +1947,9 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo, ...@@ -1979,9 +1947,9 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
if (pginfo->hwpage_cnt) { if (pginfo->hwpage_cnt) {
ehca_gen_err( ehca_gen_err(
"invalid alignment " "invalid alignment "
"pgaddr=%llx i=%x " "pgaddr=%llx entry=%llx "
"mr_pgsize=%llx", "mr_pgsize=%llx",
pgaddr, i, pgaddr, pginfo->u.usr.next_nmap,
pginfo->hwpage_size); pginfo->hwpage_size);
ret = -EFAULT; ret = -EFAULT;
return ret; return ret;
...@@ -1997,12 +1965,12 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo, ...@@ -1997,12 +1965,12 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
} }
if (ehca_debug_level >= 3) { if (ehca_debug_level >= 3) {
u64 val = *(u64 *)__va(pgaddr); u64 val = *(u64 *)__va(pgaddr);
ehca_gen_dbg("kpage=%llx chunk_page=%llx " ehca_gen_dbg("kpage=%llx page=%llx "
"value=%016llx", "value=%016llx",
*kpage, pgaddr, val); *kpage, pgaddr, val);
} }
prev_pgaddr = pgaddr; prev_pgaddr = pgaddr;
i++; *sg = sg_next(*sg);
pginfo->kpage_cnt++; pginfo->kpage_cnt++;
pginfo->u.usr.next_nmap++; pginfo->u.usr.next_nmap++;
nr_kpages--; nr_kpages--;
...@@ -2010,48 +1978,23 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo, ...@@ -2010,48 +1978,23 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
goto next_kpage; goto next_kpage;
continue; continue;
} }
if (i + nr_kpages > chunk->nmap) {
ret = ehca_check_kpages_per_ate(
chunk->page_list, i,
chunk->nmap - 1, &prev_pgaddr);
if (ret) return ret;
pginfo->kpage_cnt += chunk->nmap - i;
pginfo->u.usr.next_nmap += chunk->nmap - i;
nr_kpages -= chunk->nmap - i;
break;
}
ret = ehca_check_kpages_per_ate(chunk->page_list, i, ret = ehca_check_kpages_per_ate(sg, nr_kpages,
i + nr_kpages - 1,
&prev_pgaddr); &prev_pgaddr);
if (ret) return ret; if (ret)
i += nr_kpages; return ret;
pginfo->kpage_cnt += nr_kpages; pginfo->kpage_cnt += nr_kpages;
pginfo->u.usr.next_nmap += nr_kpages; pginfo->u.usr.next_nmap += nr_kpages;
next_kpage: next_kpage:
nr_kpages = kpages_per_hwpage; nr_kpages = kpages_per_hwpage;
(pginfo->hwpage_cnt)++; (pginfo->hwpage_cnt)++;
kpage++; kpage++;
j++; j++;
if (j >= number) break; if (j >= number)
}
if ((pginfo->u.usr.next_nmap >= chunk->nmap) &&
(j >= number)) {
pginfo->u.usr.next_nmap = 0;
prev_chunk = chunk;
break;
} else if (pginfo->u.usr.next_nmap >= chunk->nmap) {
pginfo->u.usr.next_nmap = 0;
prev_chunk = chunk;
} else if (j >= number)
break; break;
else
prev_chunk = chunk;
} }
pginfo->u.usr.next_chunk =
list_prepare_entry(prev_chunk,
(&(pginfo->u.usr.region->chunk_list)),
list);
return ret; return ret;
} }
......
...@@ -188,8 +188,8 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -188,8 +188,8 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
{ {
struct ipath_mr *mr; struct ipath_mr *mr;
struct ib_umem *umem; struct ib_umem *umem;
struct ib_umem_chunk *chunk; int n, m, entry;
int n, m, i; struct scatterlist *sg;
struct ib_mr *ret; struct ib_mr *ret;
if (length == 0) { if (length == 0) {
...@@ -202,10 +202,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -202,10 +202,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
if (IS_ERR(umem)) if (IS_ERR(umem))
return (void *) umem; return (void *) umem;
n = 0; n = umem->nmap;
list_for_each_entry(chunk, &umem->chunk_list, list)
n += chunk->nents;
mr = alloc_mr(n, &to_idev(pd->device)->lk_table); mr = alloc_mr(n, &to_idev(pd->device)->lk_table);
if (!mr) { if (!mr) {
ret = ERR_PTR(-ENOMEM); ret = ERR_PTR(-ENOMEM);
...@@ -224,11 +221,10 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -224,11 +221,10 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
m = 0; m = 0;
n = 0; n = 0;
list_for_each_entry(chunk, &umem->chunk_list, list) { for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
for (i = 0; i < chunk->nents; i++) {
void *vaddr; void *vaddr;
vaddr = page_address(sg_page(&chunk->page_list[i])); vaddr = page_address(sg_page(sg));
if (!vaddr) { if (!vaddr) {
ret = ERR_PTR(-EINVAL); ret = ERR_PTR(-EINVAL);
goto bail; goto bail;
...@@ -241,7 +237,6 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -241,7 +237,6 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
n = 0; n = 0;
} }
} }
}
ret = &mr->ibmr; ret = &mr->ibmr;
bail: bail:
......
...@@ -45,7 +45,6 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt, ...@@ -45,7 +45,6 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
struct mlx4_db *db) struct mlx4_db *db)
{ {
struct mlx4_ib_user_db_page *page; struct mlx4_ib_user_db_page *page;
struct ib_umem_chunk *chunk;
int err = 0; int err = 0;
mutex_lock(&context->db_page_mutex); mutex_lock(&context->db_page_mutex);
...@@ -73,8 +72,7 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt, ...@@ -73,8 +72,7 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
list_add(&page->list, &context->db_page_list); list_add(&page->list, &context->db_page_list);
found: found:
chunk = list_entry(page->umem->chunk_list.next, struct ib_umem_chunk, list); db->dma = sg_dma_address(page->umem->sg_head.sgl) + (virt & ~PAGE_MASK);
db->dma = sg_dma_address(chunk->page_list) + (virt & ~PAGE_MASK);
db->u.user_page = page; db->u.user_page = page;
++page->refcnt; ++page->refcnt;
......
...@@ -90,11 +90,11 @@ int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, ...@@ -90,11 +90,11 @@ int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt,
struct ib_umem *umem) struct ib_umem *umem)
{ {
u64 *pages; u64 *pages;
struct ib_umem_chunk *chunk; int i, k, entry;
int i, j, k;
int n; int n;
int len; int len;
int err = 0; int err = 0;
struct scatterlist *sg;
pages = (u64 *) __get_free_page(GFP_KERNEL); pages = (u64 *) __get_free_page(GFP_KERNEL);
if (!pages) if (!pages)
...@@ -102,11 +102,10 @@ int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, ...@@ -102,11 +102,10 @@ int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt,
i = n = 0; i = n = 0;
list_for_each_entry(chunk, &umem->chunk_list, list) for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
for (j = 0; j < chunk->nmap; ++j) { len = sg_dma_len(sg) >> mtt->page_shift;
len = sg_dma_len(&chunk->page_list[j]) >> mtt->page_shift;
for (k = 0; k < len; ++k) { for (k = 0; k < len; ++k) {
pages[i++] = sg_dma_address(&chunk->page_list[j]) + pages[i++] = sg_dma_address(sg) +
umem->page_size * k; umem->page_size * k;
/* /*
* Be friendly to mlx4_write_mtt() and * Be friendly to mlx4_write_mtt() and
......
...@@ -47,7 +47,6 @@ int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt, ...@@ -47,7 +47,6 @@ int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt,
struct mlx5_db *db) struct mlx5_db *db)
{ {
struct mlx5_ib_user_db_page *page; struct mlx5_ib_user_db_page *page;
struct ib_umem_chunk *chunk;
int err = 0; int err = 0;
mutex_lock(&context->db_page_mutex); mutex_lock(&context->db_page_mutex);
...@@ -75,8 +74,7 @@ int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt, ...@@ -75,8 +74,7 @@ int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt,
list_add(&page->list, &context->db_page_list); list_add(&page->list, &context->db_page_list);
found: found:
chunk = list_entry(page->umem->chunk_list.next, struct ib_umem_chunk, list); db->dma = sg_dma_address(page->umem->sg_head.sgl) + (virt & ~PAGE_MASK);
db->dma = sg_dma_address(chunk->page_list) + (virt & ~PAGE_MASK);
db->u.user_page = page; db->u.user_page = page;
++page->refcnt; ++page->refcnt;
......
...@@ -44,16 +44,17 @@ ...@@ -44,16 +44,17 @@
void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift, void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift,
int *ncont, int *order) int *ncont, int *order)
{ {
struct ib_umem_chunk *chunk;
unsigned long tmp; unsigned long tmp;
unsigned long m; unsigned long m;
int i, j, k; int i, k;
u64 base = 0; u64 base = 0;
int p = 0; int p = 0;
int skip; int skip;
int mask; int mask;
u64 len; u64 len;
u64 pfn; u64 pfn;
struct scatterlist *sg;
int entry;
addr = addr >> PAGE_SHIFT; addr = addr >> PAGE_SHIFT;
tmp = (unsigned long)addr; tmp = (unsigned long)addr;
...@@ -61,10 +62,9 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift, ...@@ -61,10 +62,9 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift,
skip = 1 << m; skip = 1 << m;
mask = skip - 1; mask = skip - 1;
i = 0; i = 0;
list_for_each_entry(chunk, &umem->chunk_list, list) for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
for (j = 0; j < chunk->nmap; j++) { len = sg_dma_len(sg) >> PAGE_SHIFT;
len = sg_dma_len(&chunk->page_list[j]) >> PAGE_SHIFT; pfn = sg_dma_address(sg) >> PAGE_SHIFT;
pfn = sg_dma_address(&chunk->page_list[j]) >> PAGE_SHIFT;
for (k = 0; k < len; k++) { for (k = 0; k < len; k++) {
if (!(i & mask)) { if (!(i & mask)) {
tmp = (unsigned long)pfn; tmp = (unsigned long)pfn;
...@@ -112,17 +112,17 @@ void mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem, ...@@ -112,17 +112,17 @@ void mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem,
{ {
int shift = page_shift - PAGE_SHIFT; int shift = page_shift - PAGE_SHIFT;
int mask = (1 << shift) - 1; int mask = (1 << shift) - 1;
struct ib_umem_chunk *chunk; int i, k;
int i, j, k;
u64 cur = 0; u64 cur = 0;
u64 base; u64 base;
int len; int len;
struct scatterlist *sg;
int entry;
i = 0; i = 0;
list_for_each_entry(chunk, &umem->chunk_list, list) for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
for (j = 0; j < chunk->nmap; j++) { len = sg_dma_len(sg) >> PAGE_SHIFT;
len = sg_dma_len(&chunk->page_list[j]) >> PAGE_SHIFT; base = sg_dma_address(sg);
base = sg_dma_address(&chunk->page_list[j]);
for (k = 0; k < len; k++) { for (k = 0; k < len; k++) {
if (!(i & mask)) { if (!(i & mask)) {
cur = base + (k << PAGE_SHIFT); cur = base + (k << PAGE_SHIFT);
......
...@@ -976,12 +976,12 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -976,12 +976,12 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 virt, int acc, struct ib_udata *udata) u64 virt, int acc, struct ib_udata *udata)
{ {
struct mthca_dev *dev = to_mdev(pd->device); struct mthca_dev *dev = to_mdev(pd->device);
struct ib_umem_chunk *chunk; struct scatterlist *sg;
struct mthca_mr *mr; struct mthca_mr *mr;
struct mthca_reg_mr ucmd; struct mthca_reg_mr ucmd;
u64 *pages; u64 *pages;
int shift, n, len; int shift, n, len;
int i, j, k; int i, k, entry;
int err = 0; int err = 0;
int write_mtt_size; int write_mtt_size;
...@@ -1009,10 +1009,7 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -1009,10 +1009,7 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
} }
shift = ffs(mr->umem->page_size) - 1; shift = ffs(mr->umem->page_size) - 1;
n = mr->umem->nmap;
n = 0;
list_for_each_entry(chunk, &mr->umem->chunk_list, list)
n += chunk->nents;
mr->mtt = mthca_alloc_mtt(dev, n); mr->mtt = mthca_alloc_mtt(dev, n);
if (IS_ERR(mr->mtt)) { if (IS_ERR(mr->mtt)) {
...@@ -1030,11 +1027,10 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -1030,11 +1027,10 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
write_mtt_size = min(mthca_write_mtt_size(dev), (int) (PAGE_SIZE / sizeof *pages)); write_mtt_size = min(mthca_write_mtt_size(dev), (int) (PAGE_SIZE / sizeof *pages));
list_for_each_entry(chunk, &mr->umem->chunk_list, list) for_each_sg(mr->umem->sg_head.sgl, sg, mr->umem->nmap, entry) {
for (j = 0; j < chunk->nmap; ++j) { len = sg_dma_len(sg) >> shift;
len = sg_dma_len(&chunk->page_list[j]) >> shift;
for (k = 0; k < len; ++k) { for (k = 0; k < len; ++k) {
pages[i++] = sg_dma_address(&chunk->page_list[j]) + pages[i++] = sg_dma_address(sg) +
mr->umem->page_size * k; mr->umem->page_size * k;
/* /*
* Be friendly to write_mtt and pass it chunks * Be friendly to write_mtt and pass it chunks
......
...@@ -2307,7 +2307,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2307,7 +2307,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
struct nes_device *nesdev = nesvnic->nesdev; struct nes_device *nesdev = nesvnic->nesdev;
struct nes_adapter *nesadapter = nesdev->nesadapter; struct nes_adapter *nesadapter = nesdev->nesadapter;
struct ib_mr *ibmr = ERR_PTR(-EINVAL); struct ib_mr *ibmr = ERR_PTR(-EINVAL);
struct ib_umem_chunk *chunk; struct scatterlist *sg;
struct nes_ucontext *nes_ucontext; struct nes_ucontext *nes_ucontext;
struct nes_pbl *nespbl; struct nes_pbl *nespbl;
struct nes_mr *nesmr; struct nes_mr *nesmr;
...@@ -2315,7 +2315,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2315,7 +2315,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
struct nes_mem_reg_req req; struct nes_mem_reg_req req;
struct nes_vpbl vpbl; struct nes_vpbl vpbl;
struct nes_root_vpbl root_vpbl; struct nes_root_vpbl root_vpbl;
int nmap_index, page_index; int entry, page_index;
int page_count = 0; int page_count = 0;
int err, pbl_depth = 0; int err, pbl_depth = 0;
int chunk_pages; int chunk_pages;
...@@ -2330,6 +2330,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2330,6 +2330,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u16 pbl_count; u16 pbl_count;
u8 single_page = 1; u8 single_page = 1;
u8 stag_key; u8 stag_key;
int first_page = 1;
region = ib_umem_get(pd->uobject->context, start, length, acc, 0); region = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(region)) { if (IS_ERR(region)) {
...@@ -2380,21 +2381,18 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2380,21 +2381,18 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
} }
nesmr->region = region; nesmr->region = region;
list_for_each_entry(chunk, &region->chunk_list, list) { for_each_sg(region->sg_head.sgl, sg, region->nmap, entry) {
nes_debug(NES_DBG_MR, "Chunk: nents = %u, nmap = %u .\n", if (sg_dma_address(sg) & ~PAGE_MASK) {
chunk->nents, chunk->nmap);
for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) {
if (sg_dma_address(&chunk->page_list[nmap_index]) & ~PAGE_MASK) {
ib_umem_release(region); ib_umem_release(region);
nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n", nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n",
(unsigned int) sg_dma_address(&chunk->page_list[nmap_index])); (unsigned int) sg_dma_address(sg));
ibmr = ERR_PTR(-EINVAL); ibmr = ERR_PTR(-EINVAL);
kfree(nesmr); kfree(nesmr);
goto reg_user_mr_err; goto reg_user_mr_err;
} }
if (!sg_dma_len(&chunk->page_list[nmap_index])) { if (!sg_dma_len(sg)) {
ib_umem_release(region); ib_umem_release(region);
nes_free_resource(nesadapter, nesadapter->allocated_mrs, nes_free_resource(nesadapter, nesadapter->allocated_mrs,
stag_index); stag_index);
...@@ -2404,12 +2402,12 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2404,12 +2402,12 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
goto reg_user_mr_err; goto reg_user_mr_err;
} }
region_length += sg_dma_len(&chunk->page_list[nmap_index]); region_length += sg_dma_len(sg);
chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12; chunk_pages = sg_dma_len(sg) >> 12;
region_length -= skip_pages << 12; region_length -= skip_pages << 12;
for (page_index=skip_pages; page_index < chunk_pages; page_index++) { for (page_index = skip_pages; page_index < chunk_pages; page_index++) {
skip_pages = 0; skip_pages = 0;
if ((page_count!=0)&&(page_count<<12)-(region->offset&(4096-1))>=region->length) if ((page_count != 0) && (page_count<<12)-(region->offset&(4096-1)) >= region->length)
goto enough_pages; goto enough_pages;
if ((page_count&0x01FF) == 0) { if ((page_count&0x01FF) == 0) {
if (page_count >= 1024 * 512) { if (page_count >= 1024 * 512) {
...@@ -2479,29 +2477,29 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2479,29 +2477,29 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
if (single_page) { if (single_page) {
if (page_count != 0) { if (page_count != 0) {
if ((last_dma_addr+4096) != if ((last_dma_addr+4096) !=
(sg_dma_address(&chunk->page_list[nmap_index])+ (sg_dma_address(sg)+
(page_index*4096))) (page_index*4096)))
single_page = 0; single_page = 0;
last_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+ last_dma_addr = sg_dma_address(sg)+
(page_index*4096); (page_index*4096);
} else { } else {
first_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+ first_dma_addr = sg_dma_address(sg)+
(page_index*4096); (page_index*4096);
last_dma_addr = first_dma_addr; last_dma_addr = first_dma_addr;
} }
} }
vpbl.pbl_vbase[cur_pbl_index].pa_low = vpbl.pbl_vbase[cur_pbl_index].pa_low =
cpu_to_le32((u32)(sg_dma_address(&chunk->page_list[nmap_index])+ cpu_to_le32((u32)(sg_dma_address(sg)+
(page_index*4096))); (page_index*4096)));
vpbl.pbl_vbase[cur_pbl_index].pa_high = vpbl.pbl_vbase[cur_pbl_index].pa_high =
cpu_to_le32((u32)((((u64)(sg_dma_address(&chunk->page_list[nmap_index])+ cpu_to_le32((u32)((((u64)(sg_dma_address(sg)+
(page_index*4096))) >> 32))); (page_index*4096))) >> 32)));
cur_pbl_index++; cur_pbl_index++;
page_count++; page_count++;
} }
} }
}
enough_pages: enough_pages:
nes_debug(NES_DBG_MR, "calculating stag, stag_index=0x%08x, driver_key=0x%08x," nes_debug(NES_DBG_MR, "calculating stag, stag_index=0x%08x, driver_key=0x%08x,"
" stag_key=0x%08x\n", " stag_key=0x%08x\n",
...@@ -2613,17 +2611,20 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2613,17 +2611,20 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
nespbl->pbl_size, (unsigned long) nespbl->pbl_pbase, nespbl->pbl_size, (unsigned long) nespbl->pbl_pbase,
(void *) nespbl->pbl_vbase, nespbl->user_base); (void *) nespbl->pbl_vbase, nespbl->user_base);
list_for_each_entry(chunk, &region->chunk_list, list) { for_each_sg(region->sg_head.sgl, sg, region->nmap, entry) {
for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) { chunk_pages = sg_dma_len(sg) >> 12;
chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12; chunk_pages += (sg_dma_len(sg) & (4096-1)) ? 1 : 0;
chunk_pages += (sg_dma_len(&chunk->page_list[nmap_index]) & (4096-1)) ? 1 : 0; if (first_page) {
nespbl->page = sg_page(&chunk->page_list[0]); nespbl->page = sg_page(sg);
for (page_index=0; page_index<chunk_pages; page_index++) { first_page = 0;
}
for (page_index = 0; page_index < chunk_pages; page_index++) {
((__le32 *)pbl)[0] = cpu_to_le32((u32) ((__le32 *)pbl)[0] = cpu_to_le32((u32)
(sg_dma_address(&chunk->page_list[nmap_index])+ (sg_dma_address(sg)+
(page_index*4096))); (page_index*4096)));
((__le32 *)pbl)[1] = cpu_to_le32(((u64) ((__le32 *)pbl)[1] = cpu_to_le32(((u64)
(sg_dma_address(&chunk->page_list[nmap_index])+ (sg_dma_address(sg)+
(page_index*4096)))>>32); (page_index*4096)))>>32);
nes_debug(NES_DBG_MR, "pbl=%p, *pbl=0x%016llx, 0x%08x%08x\n", pbl, nes_debug(NES_DBG_MR, "pbl=%p, *pbl=0x%016llx, 0x%08x%08x\n", pbl,
(unsigned long long)*pbl, (unsigned long long)*pbl,
...@@ -2631,7 +2632,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2631,7 +2632,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
pbl++; pbl++;
} }
} }
}
if (req.reg_type == IWNES_MEMREG_TYPE_QP) { if (req.reg_type == IWNES_MEMREG_TYPE_QP) {
list_add_tail(&nespbl->list, &nes_ucontext->qp_reg_mem_list); list_add_tail(&nespbl->list, &nes_ucontext->qp_reg_mem_list);
} else { } else {
......
...@@ -726,10 +726,10 @@ static void build_user_pbes(struct ocrdma_dev *dev, struct ocrdma_mr *mr, ...@@ -726,10 +726,10 @@ static void build_user_pbes(struct ocrdma_dev *dev, struct ocrdma_mr *mr,
u32 num_pbes) u32 num_pbes)
{ {
struct ocrdma_pbe *pbe; struct ocrdma_pbe *pbe;
struct ib_umem_chunk *chunk; struct scatterlist *sg;
struct ocrdma_pbl *pbl_tbl = mr->hwmr.pbl_table; struct ocrdma_pbl *pbl_tbl = mr->hwmr.pbl_table;
struct ib_umem *umem = mr->umem; struct ib_umem *umem = mr->umem;
int i, shift, pg_cnt, pages, pbe_cnt, total_num_pbes = 0; int shift, pg_cnt, pages, pbe_cnt, entry, total_num_pbes = 0;
if (!mr->hwmr.num_pbes) if (!mr->hwmr.num_pbes)
return; return;
...@@ -739,20 +739,18 @@ static void build_user_pbes(struct ocrdma_dev *dev, struct ocrdma_mr *mr, ...@@ -739,20 +739,18 @@ static void build_user_pbes(struct ocrdma_dev *dev, struct ocrdma_mr *mr,
shift = ilog2(umem->page_size); shift = ilog2(umem->page_size);
list_for_each_entry(chunk, &umem->chunk_list, list) { for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
/* get all the dma regions from the chunk. */ pages = sg_dma_len(sg) >> shift;
for (i = 0; i < chunk->nmap; i++) {
pages = sg_dma_len(&chunk->page_list[i]) >> shift;
for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) { for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) {
/* store the page address in pbe */ /* store the page address in pbe */
pbe->pa_lo = pbe->pa_lo =
cpu_to_le32(sg_dma_address cpu_to_le32(sg_dma_address
(&chunk->page_list[i]) + (sg) +
(umem->page_size * pg_cnt)); (umem->page_size * pg_cnt));
pbe->pa_hi = pbe->pa_hi =
cpu_to_le32(upper_32_bits cpu_to_le32(upper_32_bits
((sg_dma_address ((sg_dma_address
(&chunk->page_list[i]) + (sg) +
umem->page_size * pg_cnt))); umem->page_size * pg_cnt)));
pbe_cnt += 1; pbe_cnt += 1;
total_num_pbes += 1; total_num_pbes += 1;
...@@ -771,7 +769,7 @@ static void build_user_pbes(struct ocrdma_dev *dev, struct ocrdma_mr *mr, ...@@ -771,7 +769,7 @@ static void build_user_pbes(struct ocrdma_dev *dev, struct ocrdma_mr *mr,
pbe = (struct ocrdma_pbe *)pbl_tbl->va; pbe = (struct ocrdma_pbe *)pbl_tbl->va;
pbe_cnt = 0; pbe_cnt = 0;
} }
}
} }
} }
} }
......
...@@ -232,8 +232,8 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -232,8 +232,8 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
{ {
struct qib_mr *mr; struct qib_mr *mr;
struct ib_umem *umem; struct ib_umem *umem;
struct ib_umem_chunk *chunk; struct scatterlist *sg;
int n, m, i; int n, m, entry;
struct ib_mr *ret; struct ib_mr *ret;
if (length == 0) { if (length == 0) {
...@@ -246,9 +246,7 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -246,9 +246,7 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
if (IS_ERR(umem)) if (IS_ERR(umem))
return (void *) umem; return (void *) umem;
n = 0; n = umem->nmap;
list_for_each_entry(chunk, &umem->chunk_list, list)
n += chunk->nents;
mr = alloc_mr(n, pd); mr = alloc_mr(n, pd);
if (IS_ERR(mr)) { if (IS_ERR(mr)) {
...@@ -268,11 +266,10 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -268,11 +266,10 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
mr->mr.page_shift = ilog2(umem->page_size); mr->mr.page_shift = ilog2(umem->page_size);
m = 0; m = 0;
n = 0; n = 0;
list_for_each_entry(chunk, &umem->chunk_list, list) { for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
for (i = 0; i < chunk->nents; i++) {
void *vaddr; void *vaddr;
vaddr = page_address(sg_page(&chunk->page_list[i])); vaddr = page_address(sg_page(sg));
if (!vaddr) { if (!vaddr) {
ret = ERR_PTR(-EINVAL); ret = ERR_PTR(-EINVAL);
goto bail; goto bail;
...@@ -285,7 +282,6 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -285,7 +282,6 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
n = 0; n = 0;
} }
} }
}
ret = &mr->ibmr; ret = &mr->ibmr;
bail: bail:
......
...@@ -46,17 +46,12 @@ struct ib_umem { ...@@ -46,17 +46,12 @@ struct ib_umem {
int page_size; int page_size;
int writable; int writable;
int hugetlb; int hugetlb;
struct list_head chunk_list;
struct work_struct work; struct work_struct work;
struct mm_struct *mm; struct mm_struct *mm;
unsigned long diff; unsigned long diff;
}; struct sg_table sg_head;
struct ib_umem_chunk {
struct list_head list;
int nents;
int nmap; int nmap;
struct scatterlist page_list[0]; int npages;
}; };
#ifdef CONFIG_INFINIBAND_USER_MEM #ifdef CONFIG_INFINIBAND_USER_MEM
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment