Skip to content

Commit

Permalink
RDMA/hns: Fix mapping error of zero-hop WQE buffer
Browse files Browse the repository at this point in the history
Due to HW limitation, the three region of WQE buffer must be mapped
and set to HW in a fixed order: SQ buffer, SGE buffer, and RQ buffer.

Currently when one region is zero-hop while the other two are not,
the zero-hop region will not be mapped. This violate the limitation
above and leads to address error.

Fixes: 38389ea ("RDMA/hns: Add mtr support for mixed multihop addressing")
Signed-off-by: wenglianfa <wenglianfa@huawei.com>
Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
Link: https://patch.msgid.link/20241220055249.146943-2-huangjunxian6@hisilicon.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
  • Loading branch information
wenglianfa authored and Leon Romanovsky committed Dec 23, 2024
1 parent 9272cba commit 8673a6c
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 19 deletions.
43 changes: 29 additions & 14 deletions drivers/infiniband/hw/hns/hns_roce_hem.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,7 @@ struct hns_roce_hem_item {
size_t count; /* max ba numbers */
int start; /* start buf offset in this hem */
int end; /* end buf offset in this hem */
bool exist_bt;
};

/* All HEM items are linked in a tree structure */
Expand Down Expand Up @@ -959,6 +960,7 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
}
}

hem->exist_bt = exist_bt;
hem->count = count;
hem->start = start;
hem->end = end;
Expand All @@ -969,22 +971,22 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
}

static void hem_list_free_item(struct hns_roce_dev *hr_dev,
struct hns_roce_hem_item *hem, bool exist_bt)
struct hns_roce_hem_item *hem)
{
if (exist_bt)
if (hem->exist_bt)
dma_free_coherent(hr_dev->dev, hem->count * BA_BYTE_LEN,
hem->addr, hem->dma_addr);
kfree(hem);
}

static void hem_list_free_all(struct hns_roce_dev *hr_dev,
struct list_head *head, bool exist_bt)
struct list_head *head)
{
struct hns_roce_hem_item *hem, *temp_hem;

list_for_each_entry_safe(hem, temp_hem, head, list) {
list_del(&hem->list);
hem_list_free_item(hr_dev, hem, exist_bt);
hem_list_free_item(hr_dev, hem);
}
}

Expand Down Expand Up @@ -1084,6 +1086,10 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions,

for (i = 0; i < region_cnt; i++) {
r = (struct hns_roce_buf_region *)&regions[i];
/* when r->hopnum = 0, the region should not occupy root_ba. */
if (!r->hopnum)
continue;

if (r->hopnum > 1) {
step = hem_list_calc_ba_range(r->hopnum, 1, unit);
if (step > 0)
Expand Down Expand Up @@ -1177,7 +1183,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,

err_exit:
for (level = 1; level < hopnum; level++)
hem_list_free_all(hr_dev, &temp_list[level], true);
hem_list_free_all(hr_dev, &temp_list[level]);

return ret;
}
Expand Down Expand Up @@ -1218,16 +1224,26 @@ static int alloc_fake_root_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
{
struct hns_roce_hem_item *hem;

/* This is on the has_mtt branch, if r->hopnum
* is 0, there is no root_ba to reuse for the
* region's fake hem, so a dma_alloc request is
* necessary here.
*/
hem = hem_list_alloc_item(hr_dev, r->offset, r->offset + r->count - 1,
r->count, false);
r->count, !r->hopnum);
if (!hem)
return -ENOMEM;

hem_list_assign_bt(hem, cpu_base, phy_base);
/* The root_ba can be reused only when r->hopnum > 0. */
if (r->hopnum)
hem_list_assign_bt(hem, cpu_base, phy_base);
list_add(&hem->list, branch_head);
list_add(&hem->sibling, leaf_head);

return r->count;
/* If r->hopnum == 0, 0 is returned,
* so that the root_bt entry is not occupied.
*/
return r->hopnum ? r->count : 0;
}

static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
Expand Down Expand Up @@ -1271,7 +1287,7 @@ setup_root_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem_list *hem_list,
return -ENOMEM;

total = 0;
for (i = 0; i < region_cnt && total < max_ba_num; i++) {
for (i = 0; i < region_cnt && total <= max_ba_num; i++) {
r = &regions[i];
if (!r->count)
continue;
Expand Down Expand Up @@ -1337,9 +1353,9 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
region_cnt);
if (ret) {
for (i = 0; i < region_cnt; i++)
hem_list_free_all(hr_dev, &head.branch[i], false);
hem_list_free_all(hr_dev, &head.branch[i]);

hem_list_free_all(hr_dev, &head.root, true);
hem_list_free_all(hr_dev, &head.root);
}

return ret;
Expand Down Expand Up @@ -1402,10 +1418,9 @@ void hns_roce_hem_list_release(struct hns_roce_dev *hr_dev,

for (i = 0; i < HNS_ROCE_MAX_BT_REGION; i++)
for (j = 0; j < HNS_ROCE_MAX_BT_LEVEL; j++)
hem_list_free_all(hr_dev, &hem_list->mid_bt[i][j],
j != 0);
hem_list_free_all(hr_dev, &hem_list->mid_bt[i][j]);

hem_list_free_all(hr_dev, &hem_list->root_bt, true);
hem_list_free_all(hr_dev, &hem_list->root_bt);
INIT_LIST_HEAD(&hem_list->btm_bt);
hem_list->root_ba = 0;
}
Expand Down
5 changes: 0 additions & 5 deletions drivers/infiniband/hw/hns/hns_roce_mr.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,11 +814,6 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
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) {
ret = -EINVAL;
Expand Down

0 comments on commit 8673a6c

Please sign in to comment.