RDMA/hns: Add mapped page count checking for MTR
Add the mapped page count checking flow to avoid invalid page size when creating MTR. Fixes: 38389eaa4db1 ("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>
This commit is contained in:
parent
ea4092f3b5
commit
9ea9a53ea9
@ -1075,9 +1075,8 @@ static struct roce_hem_item *hem_list_alloc_item(struct hns_roce_dev *hr_dev,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (exist_bt) {
|
if (exist_bt) {
|
||||||
hem->addr = dma_alloc_coherent(hr_dev->dev,
|
hem->addr = dma_alloc_coherent(hr_dev->dev, count * BA_BYTE_LEN,
|
||||||
count * BA_BYTE_LEN,
|
&hem->dma_addr, GFP_KERNEL);
|
||||||
&hem->dma_addr, GFP_KERNEL);
|
|
||||||
if (!hem->addr) {
|
if (!hem->addr) {
|
||||||
kfree(hem);
|
kfree(hem);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1336,6 +1335,10 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
|
|||||||
if (ba_num < 1)
|
if (ba_num < 1)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (ba_num > unit)
|
||||||
|
return -ENOBUFS;
|
||||||
|
|
||||||
|
ba_num = min_t(int, ba_num, unit);
|
||||||
INIT_LIST_HEAD(&temp_root);
|
INIT_LIST_HEAD(&temp_root);
|
||||||
offset = r->offset;
|
offset = r->offset;
|
||||||
/* indicate to last region */
|
/* indicate to last region */
|
||||||
|
@ -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,
|
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;
|
__le64 *mtts;
|
||||||
int offset;
|
|
||||||
int count;
|
|
||||||
int npage;
|
|
||||||
u64 addr;
|
u64 addr;
|
||||||
int end;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* if hopnum is 0, buffer cannot store BAs, so skip write mtt */
|
|
||||||
if (!region->hopnum)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
offset = region->offset;
|
offset = region->offset;
|
||||||
end = offset + region->count;
|
end = offset + region->count;
|
||||||
npage = 0;
|
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,
|
mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list,
|
||||||
offset, &count, NULL);
|
offset, &count, NULL);
|
||||||
if (!mtts)
|
if (!mtts)
|
||||||
return -ENOBUFS;
|
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)
|
if (hr_dev->hw_rev == HNS_ROCE_HW_VER1)
|
||||||
addr = to_hr_hw_page_addr(pages[npage]);
|
addr = to_hr_hw_page_addr(pages[npage]);
|
||||||
else
|
else
|
||||||
@ -631,7 +627,7 @@ static int mtr_map_region(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|||||||
offset += count;
|
offset += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return npage;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool mtr_has_mtt(struct hns_roce_buf_attr *attr)
|
static inline bool mtr_has_mtt(struct hns_roce_buf_attr *attr)
|
||||||
@ -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 ib_device *ibdev = &hr_dev->ib_dev;
|
||||||
struct hns_roce_buf_region *r;
|
struct hns_roce_buf_region *r;
|
||||||
unsigned int i;
|
unsigned int i, mapped_cnt;
|
||||||
int err;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only use the first page address as root ba when hopnum is 0, this
|
* Only use the first page address as root ba when hopnum is 0, this
|
||||||
@ -791,26 +787,42 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|||||||
return 0;
|
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];
|
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) {
|
if (r->offset + r->count > page_cnt) {
|
||||||
err = -EINVAL;
|
ret = -EINVAL;
|
||||||
ibdev_err(ibdev,
|
ibdev_err(ibdev,
|
||||||
"failed to check mtr%u end %u + %u, max %u.\n",
|
"failed to check mtr%u end %u + %u, max %u.\n",
|
||||||
i, r->offset, r->count, page_cnt);
|
i, r->offset, r->count, page_cnt);
|
||||||
return err;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mtr_map_region(hr_dev, mtr, &pages[r->offset], r);
|
ret = mtr_map_region(hr_dev, mtr, r, &pages[r->offset],
|
||||||
if (err) {
|
page_cnt - mapped_cnt);
|
||||||
|
if (ret < 0) {
|
||||||
ibdev_err(ibdev,
|
ibdev_err(ibdev,
|
||||||
"failed to map mtr%u offset %u, ret = %d.\n",
|
"failed to map mtr%u offset %u, ret = %d.\n",
|
||||||
i, r->offset, err);
|
i, r->offset, ret);
|
||||||
return err;
|
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,
|
int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user