Skip to content

Commit 60c3bec

Browse files
wangxi11jgunthorpe
authored andcommitted
RDMA/hns: Fix sg offset non-zero issue
When run perftest in many times, the system will report a BUG as follows: BUG: Bad rss-counter state mm:(____ptrval____) idx:0 val:-1 BUG: Bad rss-counter state mm:(____ptrval____) idx:1 val:1 We tested with different kernel version and found it started from the the following commit: commit d10bcf9 ("RDMA/umem: Combine contiguous PAGE_SIZE regions in SGEs") In this commit, the sg->offset is always 0 when sg_set_page() is called in ib_umem_get() and the drivers are not allowed to change the sgl, otherwise it will get bad page descriptor when unfolding SGEs in __ib_umem_release() as sg_page_count() will get wrong result while sgl->offset is not 0. However, there is a weird sgl usage in the current hns driver, the driver modified sg->offset after calling ib_umem_get(), which caused we iterate past the wrong number of pages in for_each_sg_page iterator. This patch fixes it by correcting the non-standard sgl usage found in the hns_roce_db_map_user() function. Fixes: d10bcf9 ("RDMA/umem: Combine contiguous PAGE_SIZE regions in SGEs") Fixes: 0425e3e ("RDMA/hns: Support flush cqe for hip08 in kernel space") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Xi Wang <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent d5121ff commit 60c3bec

File tree

1 file changed

+8
-7
lines changed

1 file changed

+8
-7
lines changed

drivers/infiniband/hw/hns/hns_roce_db.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
1212
struct ib_udata *udata, unsigned long virt,
1313
struct hns_roce_db *db)
1414
{
15+
unsigned long page_addr = virt & PAGE_MASK;
1516
struct hns_roce_user_db_page *page;
17+
unsigned int offset;
1618
int ret = 0;
1719

1820
mutex_lock(&context->page_mutex);
1921

2022
list_for_each_entry(page, &context->page_list, list)
21-
if (page->user_virt == (virt & PAGE_MASK))
23+
if (page->user_virt == page_addr)
2224
goto found;
2325

2426
page = kmalloc(sizeof(*page), GFP_KERNEL);
@@ -28,8 +30,8 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
2830
}
2931

3032
refcount_set(&page->refcount, 1);
31-
page->user_virt = (virt & PAGE_MASK);
32-
page->umem = ib_umem_get(udata, virt & PAGE_MASK, PAGE_SIZE, 0, 0);
33+
page->user_virt = page_addr;
34+
page->umem = ib_umem_get(udata, page_addr, PAGE_SIZE, 0, 0);
3335
if (IS_ERR(page->umem)) {
3436
ret = PTR_ERR(page->umem);
3537
kfree(page);
@@ -39,10 +41,9 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
3941
list_add(&page->list, &context->page_list);
4042

4143
found:
42-
db->dma = sg_dma_address(page->umem->sg_head.sgl) +
43-
(virt & ~PAGE_MASK);
44-
page->umem->sg_head.sgl->offset = virt & ~PAGE_MASK;
45-
db->virt_addr = sg_virt(page->umem->sg_head.sgl);
44+
offset = virt - page_addr;
45+
db->dma = sg_dma_address(page->umem->sg_head.sgl) + offset;
46+
db->virt_addr = sg_virt(page->umem->sg_head.sgl) + offset;
4647
db->u.user_page = page;
4748
refcount_inc(&page->refcount);
4849

0 commit comments

Comments
 (0)