Skip to content

Commit

Permalink
RDMA/hns: Add mapped page count checking for MTR
Browse files Browse the repository at this point in the history
Add the mapped page count checking flow to avoid invalid page size when
creating MTR.

Fixes: 38389ea ("RDMA/hns: Add mtr support for mixed multihop addressing")
Link: https://lore.kernel.org/r/1612517974-31867-4-git-send-email-liweihang@huawei.com
Signed-off-by: Xi Wang <wangxi11@huawei.com>
Signed-off-by: Weihang Li <liweihang@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
  • Loading branch information
Xi Wang authored and Jason Gunthorpe committed Feb 9, 2021
1 parent ea4092f commit 9ea9a53
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 25 deletions.
9 changes: 6 additions & 3 deletions drivers/infiniband/hw/hns/hns_roce_hem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1075,9 +1075,8 @@ static struct roce_hem_item *hem_list_alloc_item(struct hns_roce_dev *hr_dev,
return NULL;

if (exist_bt) {
hem->addr = dma_alloc_coherent(hr_dev->dev,
count * BA_BYTE_LEN,
&hem->dma_addr, GFP_KERNEL);
hem->addr = dma_alloc_coherent(hr_dev->dev, count * BA_BYTE_LEN,
&hem->dma_addr, GFP_KERNEL);
if (!hem->addr) {
kfree(hem);
return NULL;
Expand Down Expand Up @@ -1336,6 +1335,10 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
if (ba_num < 1)
return -ENOMEM;

if (ba_num > unit)
return -ENOBUFS;

ba_num = min_t(int, ba_num, unit);
INIT_LIST_HEAD(&temp_root);
offset = r->offset;
/* indicate to last region */
Expand Down
56 changes: 34 additions & 22 deletions drivers/infiniband/hw/hns/hns_roce_mr.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,30 +596,26 @@ int hns_roce_dealloc_mw(struct ib_mw *ibmw)
}

static int mtr_map_region(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
dma_addr_t *pages, struct hns_roce_buf_region *region)
struct hns_roce_buf_region *region, dma_addr_t *pages,
int max_count)
{
int count, npage;
int offset, end;
__le64 *mtts;
int offset;
int count;
int npage;
u64 addr;
int end;
int i;

/* if hopnum is 0, buffer cannot store BAs, so skip write mtt */
if (!region->hopnum)
return 0;

offset = region->offset;
end = offset + region->count;
npage = 0;
while (offset < end) {
while (offset < end && npage < max_count) {
count = 0;
mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list,
offset, &count, NULL);
if (!mtts)
return -ENOBUFS;

for (i = 0; i < count; i++) {
for (i = 0; i < count && npage < max_count; i++) {
if (hr_dev->hw_rev == HNS_ROCE_HW_VER1)
addr = to_hr_hw_page_addr(pages[npage]);
else
Expand All @@ -631,7 +627,7 @@ static int mtr_map_region(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
offset += count;
}

return 0;
return npage;
}

static inline bool mtr_has_mtt(struct hns_roce_buf_attr *attr)
Expand Down Expand Up @@ -779,8 +775,8 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
{
struct ib_device *ibdev = &hr_dev->ib_dev;
struct hns_roce_buf_region *r;
unsigned int i;
int err;
unsigned int i, mapped_cnt;
int ret;

/*
* Only use the first page address as root ba when hopnum is 0, this
Expand All @@ -791,26 +787,42 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
return 0;
}

for (i = 0; i < mtr->hem_cfg.region_count; i++) {
for (i = 0, mapped_cnt = 0; i < mtr->hem_cfg.region_count &&
mapped_cnt < page_cnt; i++) {
r = &mtr->hem_cfg.region[i];
/* if hopnum is 0, no need to map pages in this region */
if (!r->hopnum) {
mapped_cnt += r->count;
continue;
}

if (r->offset + r->count > page_cnt) {
err = -EINVAL;
ret = -EINVAL;
ibdev_err(ibdev,
"failed to check mtr%u end %u + %u, max %u.\n",
i, r->offset, r->count, page_cnt);
return err;
return ret;
}

err = mtr_map_region(hr_dev, mtr, &pages[r->offset], r);
if (err) {
ret = mtr_map_region(hr_dev, mtr, r, &pages[r->offset],
page_cnt - mapped_cnt);
if (ret < 0) {
ibdev_err(ibdev,
"failed to map mtr%u offset %u, ret = %d.\n",
i, r->offset, err);
return err;
i, r->offset, ret);
return ret;
}
mapped_cnt += ret;
ret = 0;
}

return 0;
if (mapped_cnt < page_cnt) {
ret = -ENOBUFS;
ibdev_err(ibdev, "failed to map mtr pages count: %u < %u.\n",
mapped_cnt, page_cnt);
}

return ret;
}

int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
Expand Down

0 comments on commit 9ea9a53

Please sign in to comment.